Django中class-based view的使用示例

Django中class-based view的使用示例

代碼如下:

""" class-based view """
from django.db.models import Q
from django.shortcuts import get_object_or_404
from django.views.generic import ListView, DetailView

from config.models import SideBar
from .models import Post, Tag, Category


# 公共view
class CommonViewMixin:
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context.update({
            'sidebars': SideBar.get_all(),
        })
        context.update(Category.get_navs())
        return context


# 處理首頁的HTTP請求view
class IndexView(CommonViewMixin, ListView):
    queryset = Post.latest_posts()  # 獲取數據
    paginate_by = 5  # 每頁顯示的記錄數量
    context_object_name = 'post_list'  # 設置queryset的變量名稱,用於在模板中調用
    template_name = 'blog/list.html'  # 渲染使用的模板文件


# category列表頁view
class CategoryView(IndexView):
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        category_id = self.kwargs.get('category_id')
        category = get_object_or_404(Category, pk=category_id)
        context.update({
            'category': category,
        })
        return context

    def get_queryset(self):
        """ 重寫queryset,根據分類過濾 """
        queryset = super().get_queryset()  # 此處返回IndexView的queryset屬性
        category_id = self.kwargs.get('category_id')
        return queryset.filter(category_id=category_id)  # 關鍵字參數:一對一外鍵category_id


# tag列表頁view
class TagView(IndexView):
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        tag_id = self.kwargs.get('tag_id')
        tag = get_object_or_404(Tag, pk=tag_id)
        context.update({
            'tag': tag,
        })
        return context

    def get_queryset(self):
        """ 重寫queryset,根據標籤過濾"""
        queryset = super().get_queryset()  # 此處返回IndexView的queryset屬性
        tag_id = self.kwargs.get('tag_id')
        return queryset.filter(tag__id=tag_id)  # 關鍵字參數:多對多外鍵要tag__id


# 文章詳情頁view
class PostDetailView(CommonViewMixin, DetailView):
    queryset = Post.latest_posts()
    template_name = 'blog/detail.html'
    context_object_name = 'post'  # 設置傳遞到模板文件的變量名稱
    pk_url_kwarg = 'post_id'  # 在DetailView中,會根據這個參數來過濾數據,如:post = queryset.filter(pk=post_id)


# 搜索列表頁view
class SearchView(IndexView):
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context.update({
            'keyword': self.request.GET.get('keyword', '')
        })
        return context

    def get_queryset(self):
        queryset = super().get_queryset()
        keyword = self.request.GET.get('keyword', '')
        if not keyword:
            return queryset
        return queryset.filter(Q(title__icontains=keyword) | Q(desc__icontains=keyword))


# 根據作者過濾的列表頁view
class AuthorView(IndexView):
    def get_queryset(self):
        queryset = super().get_queryset()
        author_id = self.kwargs.get('owner_id')
        return queryset.filter(owner_id=author_id)

代碼分析:

代碼中的註釋已經很好地解釋了上面的代碼。
1、class CommonViewMixin:
在這個公共類view,我們通過重寫get_context_data函數來獲取一些公用的數據,這些數據在各種頁面中都需要展示,如:導航欄、側邊欄的數據

2、class IndexView(CommonViewMixin, ListView):
這個類繼承了CommonViewMixin, ListView這兩個類,實現了首頁列表頁的視圖函數。
通過設置queryset屬性來獲取數據庫中的文章數據:

queryset = Post.latest_posts()  # 獲取數據

其他的屬性說明在代碼中有註釋。
3、對於CategoryView(IndexView)、TagView(IndexView)、SearchView(IndexView)、AuthorView(IndexView):
這幾個類view都繼承了類IndexView(CommonViewMixin, ListView)
(1)通過重寫get_context_data()函數來添加額外要獲取的數據。
(2)通過重寫get_queryset(self)函數來對IndexView(CommonViewMixin, ListView)中獲取到queryset數據進行過濾。原因如下:
在CategoryView(IndexView)、TagView(IndexView)、SearchView(IndexView)、AuthorView(IndexView)這幾個類get_queryset(self)函數中調用了父類的get_queryset(self)函數:

queryset = super().get_queryset()

因爲在IndexView(CommonViewMixin, ListView)中設置了queryset屬性:

queryset = Post.latest_posts()  # 獲取數據

所以CategoryView(IndexView)、TagView(IndexView)、SearchView(IndexView)、AuthorView(IndexView)的這行代碼:

queryset = super().get_queryset()

返回的即是父類IndexView(CommonViewMixin, ListView)的queryset屬性。
接着,就可以對queryset 數據進行過濾了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章