亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

基于django的視頻點播網站開發-step4-首頁功能

發布時間:2020-04-08 18:36:13 來源:網絡 閱讀:277 作者:net19880504 欄目:編程語言

在本講中,我們開始首頁功能的開發,在開發過程中,大家將會學習到Django中的通用視圖類、分頁對象paginator以及foreignKey外鍵的使用。

效果演示
基于django的視頻點播網站開發-step4-首頁功能cdn.xitu.io/2019/1/15/16851ab0d057a5d6?w=1000&h=649&f=png&s=721688">

整體功能

大家可先通過 網站演示地址 瀏覽一下首頁的效果。我們首頁呢,比較簡潔大方,讓人一目了然。我這樣設計的目的呢,是讓大家把精力放到學習django上面來,不必過度關注花哨的頁面效果。

我們把首頁拆解為4個小的業務模塊來開發,分別是:列表顯示、分頁功能、搜索功能、分類功能。下面我們分別對這四個功能模塊進行開發講解。

開發思路

開發一個功能的基本思路是:先新建應用,然后分析功能涉及到哪些業務,從而分析出需要的數據庫字段,然后編寫模型,之后就是展示階段,通過url路由配置視圖函數,來將模型里面的數據顯示出來。

ok,我們通過命令建立應用,命名為video。執行后,django將為我們新建video文件夾。

python3 manage.py startapp video

下面的功能模塊開發都在該應用(video)下進行。

建模型

此處,我們需要建立兩個模型,分別是分類表(classification)和視頻表(video)。他們是多對一的關系(一個分類對應多個視頻,一個視頻對應一個分類)。

首先編寫Classification表,在model.py下面,我們鍵入如下代碼。
字段有title(分類名稱)和status(是否啟用)

class Classification(models.Model):
    list_display = ("title",)
    title = models.CharField(max_length=100,blank=True, null=True)
    status = models.BooleanField(default=True)

    class Meta:
        db_table = "v_classification"

字段說明

  • title 分類名稱。數據類型是CharField,最大長度為max_length=100,允許為空null=True
  • status 是否啟用。數據類型是BooleanField,默認為default=True
  • db_table 表名

然后編寫Video模型,根據網站業務,我們設置了title(標題)、 desc(描述)、 classification(分類)、file(視頻文件)、cover(封面)、status(發布狀態)等字段。其中classification是一個ForeignKey外鍵字段,表示一個分類對應多個視頻,一個視頻對應一個分類(多對一)

class Video(models.Model):
    STATUS_CHOICES = (
        ('0', '發布中'),
        ('1', '未發布'),
    )
    title = models.CharField(max_length=100,blank=True, null=True)
    desc = models.CharField(max_length=255,blank=True, null=True)
    classification = models.ForeignKey(Classification, on_delete=models.CASCADE, null=True)
    file = models.FileField(max_length=255)
    cover = models.ImageField(upload_to='cover/',blank=True, null=True)
    status = models.CharField(max_length=1 ,choices=STATUS_CHOICES, blank=True, null=True)
    create_time = models.DateTimeField(auto_now_add=True, blank=True, max_length=20)

字段說明

  • title 視頻標題。數據類型是charField,最大長度為max_length=100,允許為空null=True
  • desc 視頻描述。數據類型是charField,最大長度為max_length=255,允許為空null=True
  • file 視頻文件地址。數據類型是fileField。其中存的是視頻文件的地址,在之后的視頻管理中我們將會對視頻的上傳進行具體的講解。
  • cover 視頻封面。數據類型是ImageField。存儲目錄為upload_to='cover/',允許為空null=True
  • status 視頻狀態。是一個選擇狀態,用choices設置多選元祖。
  • create_time 創建時間。數據類型是DateTimeField 。設置自動生成時間auto_now_add=True

ForeignKey 表明一種一對多的關聯關系。比如這里我們的視頻和分類的關系,一個視頻只能對應一個分類,而一個分類下可以有多個視頻。
更多關于ForeinkKey的說明,可以參看 ForeignKey官方介紹

列表顯示

要想訪問到首頁,必須先配置好路由。在video下建立urls.py文件,寫入如下代碼

from django.urls import path
from . import views

app_name = 'video'
urlpatterns = [
    path('index', views.IndexView.as_view(), name='index'),
]

一條path語句就代表一條路由信息。這樣我們就可以在瀏覽器輸入127.0.0.1:8000/video/index來訪問首頁了。

顯示列表數據非常簡單,我們使用django中內置的視圖模版類ListView來顯示,首先在view.py中編寫IndexView類,用它來顯示列表數據。鍵入如下代碼

class IndexView(generic.ListView):
    model = Video
    template_name = 'video/index.html'
    context_object_name = 'video_list'  

此處,我們使用了django提供的通用視圖類ListView, ListView使用很簡單,只需要我們簡單的配置幾行代碼,即可將數據庫里面的數據渲染到前端。比如上述代碼中,我們配置了

  • model = Video, 作用于Video模型
  • template_name = 'video/index.html' ,告訴ListView要使用我們已經創建的模版文件。
  • context_object_name = 'video_list' ,上下文變量名,告訴ListView,在前端模版文件中,可以使用該變量名來展現數據。

之后,我們在templates文件夾下,建立video目錄,用來存放視頻相關的模板文件,首先我們創建首頁文件index.html。并將剛才獲取到的數據顯示出來。

<div class="ui grid">
    {% for item in video_list %}
    <div class="four wide column">
        <div class="ui card">
            <a class="image">
                {% thumbnail item.cover "300x200" crop="center" as im %}
                <img class="ui image" src="{{ im.url }}">
                {% empty %}
                {% endthumbnail %}
                <i class="large play icon v-play-icon"></i>
            </a>
            <div class="content">
                <a class="header">{{ item.title }}</a>
                <div class="meta">
                    <span class="date">發布于{{ item.create_time|time_since}}</span>
                </div>
                <div class="description">
                    {{ item.view_count}}次觀看
                </div>
            </div>
        </div>
    </div>
    {% empty %}
    <h4>暫無數據</h4>
    {% endfor %}
</div>

通過for循環,將video_list渲染到前端。這里我們使用到了django中的內置標簽,比如for語句、empty語句。這些都是django中非常常用的語句。在之后的教程中我們會經常遇到。

另外,還使用了thumbnail標簽來顯示圖片,thumbnail是一個很常用的python庫,常常被用來做圖片顯示。

顯示結果如下
基于django的視頻點播網站開發-step4-首頁功能

分類功能

在寫分類功能之前,我們先學習一個回調函數 get_context_data() 這是ListView視圖類中的一個函數,在 get_context_data() 函數中,可以傳一些額外內容到模板。因此我們可以使用該函數來傳遞分類數據。

要使用它,很簡單。

只需要在IndexView類下面,追加get_context_data()的實現即可。

class IndexView(generic.ListView):
    model = Video
    template_name = 'video/index.html'
    context_object_name = 'video_list' 

    def get_context_data(self, *, object_list=None, **kwargs):
        context = super(IndexView, self).get_context_data(**kwargs)
        classification_list = Classification.objects.filter(status=True).values()
        context['classification_list'] = classification_list
        return context

在上述代碼中,我們將分類數據通過Classification.objects.filter(status=True).values()從數據庫里面過濾出來,然后賦給classification_list,最后放到context字典里面。

在前端模板(templates/video/index.html)中,就可以通過classification_list來取數據。添加代碼

<div class="classification">
    <a class="ui red label" href="">全部</a>
    {% for item in classification_list %}
    <a class="ui label" href="">{{ item.title }}</a>
    {% endfor %}
</div>

顯示效果如下
基于django的視頻點播網站開發-step4-首頁功能

當然現在只是實現了分類展示效果,我們還需要繼續實現點擊效果,即點擊不同的分類,顯示不同的視頻列表。

我們先給每個分類按鈕加上href鏈接

<div class="classification">
    <a class="ui red label" href="{% url 'home' %}">全部</a>
    {% for item in classification_list %}
    <a class="ui label" href="?c={{ item.id }}">{{ item.title }}</a>
    {% endfor %}
</div>

通過添加?c={{ item.id }} 這里用c代表分類的id,點擊后,會傳到視圖類中,在視圖類中,我們使用 get_queryset() 函數,將get數據取出來。通過self.request.GET.get("c", None) 賦給c,判斷c是否為None,如果為None,就響應全部,如果有值,就通過get_object_or_404(Classification, pk=self.c)先獲取當前類,然后classification.video_set獲取外鍵數據。

    def get_queryset(self):
        self.c = self.request.GET.get("c", None)
        if self.c:
            classification = get_object_or_404(Classification, pk=self.c)
            return classification.video_set.all().order_by('-create_time')
        else:
            return Video.objects.filter(status=0).order_by('-create_time')

更多關于ForeignKey的使用方法,可參考 這里

分頁功能

在Django中,有現成的分頁解決方案,我們開發者省了不少事情。如果是簡單的分頁,只需要配置一下paginate_by即可實現。

class IndexView(generic.ListView):
    model = Video
    template_name = 'video/index.html'
    context_object_name = 'video_list'
    paginate_by = 12
    c = None
  • painate_by = 12每頁顯示12條

這樣每頁的分頁數據就能正確的顯示出來來,現在來完善底部的頁碼條。

基于django的視頻點播網站開發-step4-首頁功能

頁碼列表需要視圖類和模板共同來完成,我們先來寫視圖類。在前面我們已經寫過get_context_data了,該函數的主要功能就是傳遞額外的數據給模板。這里,我們就利用get_context_data來傳遞頁碼數據。

我們先定義一個工具函數,叫get_page_list。 在項目根目錄下,新建一個文件helpers.py該文件當作一個全局的工具類,用來存放各種工具函數。把get_page_list放到helpers.py里面 該函數用來生產頁碼列表,不但這里可以使用,以后在其他地方也可以調用該函數。

def get_page_list(paginator, page):

    page_list = []

    if paginator.num_pages > 10:
        if page.number <= 5:
            start_page = 1
        elif page.number > paginator.num_pages - 5:
            start_page = paginator.num_pages - 9
        else:
            start_page = page.number - 5

        for i in range(start_page, start_page + 10):
            page_list.append(i)
    else:
        for i in range(1, paginator.num_pages + 1):
            page_list.append(i)

    return page_list

分頁邏輯:

if 頁數>=10:
    當前頁<=5時,起始頁為1
    當前頁>(總頁數-5)時,起始頁為(總頁數-9)
    其他情況 起始頁為(當前頁-5)

舉例:

假設一共16頁
情況1: 當前頁==5  則頁碼列表為[1,2,3,4,5,6,7,8,9,10]
情況2: 當前頁==8  則頁碼列表為[3,4,5,6,7,8,9,10,11,12]
情況3: 當前頁==15 則頁碼列表為[7,8,9,10,11,12,13,14,15,16]

當然你看到這個邏輯會有點亂,建議大家讀著代碼,多試驗幾遍。

當拿到頁碼列表,我們繼續改寫get_context_data()函數。 將獲取到的classification_list追加到context字典中。

    def get_context_data(self, *, object_list=None, **kwargs):
        context = super(IndexView, self).get_context_data(**kwargs)
        paginator = context.get('paginator')
        page = context.get('page_obj')
        page_list = get_page_list(paginator, page)
        classification_list = Classification.objects.filter(status=True).values()
        context['c'] = self.c
        context['classification_list'] = classification_list
        context['page_list'] = page_list
        return context

你或許對 paginator = context.get('paginator') page = context.get('page_obj')這兩行代碼感到陌生,我們只需要知道context.get('page_obj')返回的是當前頁碼,context.get('paginator')返回的是分頁對象,就夠了。更加詳細的介紹,可參考官方。

當數據傳遞給模板之后,模板就負責顯示出來就行了。

因為分頁功能比較常用,所以需要把它單獨拿出來封裝到一個單獨的文件中,我們新建templates/base/page_nav.html文件。然后在index.html里面我們將該文件include進來。

{% include "base/page_nav.html" %}

打開page_nav.html,寫入代碼

{% if is_paginated %}
<div class="video-page">
    <div class="ui circular labels">
        {% if page_obj.has_previous %}
        <a class="ui circular label" href="?page={{ page_obj.previous_page_number }}{% if c %}&c={{c}}{% endif %}{% if q %}&q={{q}}{% endif %}">&lt;</a>
        {% endif %}
        {% for i in page_list %}
        {% if page_obj.number == i %}
        <a class="ui red circular label">{{ i }}</a>
        {% else %}
        <a class="ui circular label" href="?page={{ i }}{% if c %}&c={{c}}{% endif %}{% if q %}&q={{q}}{% endif %}">{{ i }}</a>
        {% endif %}
        {% endfor %}
        {% if page_obj.has_next %}
        <a class="ui circular label" href="?page={{ page_obj.next_page_number }}{% if c %}&c={{c}}{% endif %}{% if q %}&q={{q}}{% endif %}">&gt;</a>
        {% endif %}
    </div>
</div>
{% endif %}

上面代碼中,我們用到了page_obj對象的幾個屬性:has_previous、previous_page_number、next_page_number。通過這幾個屬性,即可實現復雜的頁碼顯示效果。其中我們還這href里面加了

{% if c %}&c={{c}}

代表分類的id。

搜索功能

要實現搜索,我們需要一個搜索框

因為搜索框是很多頁面都需要的,所以我們把代碼寫到templates/base/header.html文件里面。

<div class="ui small icon input v-video-search">
    <input class="prompt" value="{{ q }}" type="text" placeholder="搜索視頻" id="v-search">
    <i id="search" class="search icon" ></i>
</div>

點擊搜索或回車的代碼寫在了static/js/header.js里面。

我們還需要配置一下路由,添加一行搜索的路由。

app_name = 'video'
urlpatterns = [
    path('index', views.IndexView.as_view(), name='index'),
    path('search/', views.SearchListView.as_view(), name='search'),
]

搜索路由指向的視圖類為SearchListView

下面我們來寫SearchListView的代碼

class SearchListView(generic.ListView):
    model = Video
    template_name = 'video/search.html'
    context_object_name = 'video_list'
    paginate_by = 8
    q = ''

    def get_queryset(self):
        self.q = self.request.GET.get("q","")
        return Video.objects.filter(title__contains=self.q).filter(status=0)

    def get_context_data(self, *, object_list=None, **kwargs):
        context = super(SearchListView, self).get_context_data(**kwargs)
        paginator = context.get('paginator')
        page = context.get('page_obj')
        page_list = get_page_list(paginator, page)
        context['page_list'] = page_list
        context['q'] = self.q
        return context

關鍵代碼就是Video.objects.filter(titlecontains=self.q).filter(status=0)
title
contains是包含的意思,表示查詢title包含q的記錄。利用filter將數據過濾出來。這里寫了兩層過濾,第一層過濾搜索關鍵詞,第二層過濾status已發布的視頻。

另外,這里也用到了get_context_data來存放額外的數據,包括分頁數據、q關鍵詞。

配置模板文件是templates/video/search.html

因此模板代碼寫在search.html里面

<div class="ui unstackable items">

    {% for item in video_list %}
    <div class="item">
        <div class="ui tiny image">
            {% thumbnail item.cover "300x200" crop="center" as im %}
            <img class="ui image" src="{{ im.url }}">
            {% empty %}
            {% endthumbnail %}
        </div>
        <div class="middle aligned content">
          <a class="header" href="{% url 'video:detail' item.pk %}">{{ item.title }}</a>
        </div>
    </div>
    {% empty %}
    <h4>暫無數據</h4>
    {% endfor %}

</div>

{% include "base/page_nav.html" %}

搜索功能效果
基于django的視頻點播網站開發-step4-首頁功能

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

寿光市| 武乡县| 西林县| 来宾市| 若尔盖县| 闽清县| 曲阳县| 涟水县| 临沧市| 宜昌市| 曲沃县| 南和县| 长垣县| 金山区| 青岛市| 屏边| 龙江县| 黔江区| 老河口市| 旬阳县| 南开区| 财经| 巫山县| 正镶白旗| 阜宁县| 五河县| 巴彦县| 麻城市| 农安县| 商南县| 衡南县| 环江| 郧西县| 泰安市| 运城市| 彭水| 仪征市| 师宗县| 浦东新区| 库车县| 胶州市|