在早期,我們認識到在視圖開發過程中有共同的用法和模式。這時我們引入基於函數的通用視圖來抽象這些模式以簡化常見情形的視圖開發。
基於函數視圖的用法有以下三種:
def index(request): return HttpResponse('hello world!') def index(request): result = {'demo':'demo'} return render(request, 'blog/about.html', result) def index(request): result = {'demo':'demo'} return render_to_response('blog/about.html', result)
基於函數的視圖的問題在於,雖然它們很好地覆蓋了簡單的情形,但是不能擴展或自定義它們,即使是一些簡單的配置選項,這讓它們在現實應用中受到很多限制。基於類的通用視圖然后應運而生,目的與基於函數的通用視圖一樣,就是為了使得視圖的開發更加容易。
下面三個是最常使用的基於類的通用視圖:
TemplateView,ListView,DetailView
TemplateView
TemplateView
一般只在需要返回模板時使用。
class ProtectView(TemplateView): template_name = 'polls/name.html'
TemplateView
可以方便的定義要返回的模板但它不能把數據庫中的內容查詢展示出來,所以需要使用 DetailView
和 ListView
。
所有基於類的通用視圖中定義的方法需要在類視圖調用
as_view()
方法后會被自動調用,因為 Django 的URL
解析器將請求和關聯的參數發送給一個可調用的函數而不是一個類,所以基於類的視圖有一個as_view()
類方法用來作為類的可調用入口。
ListView
ListView
用於獲取存儲在數據庫中的某個 Model
的列表。
class IndexView(ListView): """ 首頁視圖函數,繼承 ListView ,展示從數據庫中獲取的文章列表 """ template_name = "blog/index.html" context_object_name = "article_list" model = Article
template_name
屬性指定了需要渲染的模板,context_object_name
指定了模板中使用的上下文變量,model
指定了數據的來源。它的功能相當於取出了 model
中 Article
的所有數據,使用變量 article_list
傳遞給了 blog/index.html
模板。ListView
中默認使用 object_list
作為上下文變量,可以使用 context_object_name
來自定義上下文變量,一般使用默認的對模板設計者不友好,所以都是自定義上下文變量的。model
屬性指定了要獲取表中的所有數據,它的功能相當於 article_list = Article.objects.all()
,但是當你需要使用過濾條件或者對數據進行一定的操作時,則需要重寫 ListView
中獲取數據的方法(get_queryset 方法),像下面這樣:
class IndexView(ListView): """ 首頁視圖函數,繼承 ListView ,展示從數據庫中獲取的文章列表 """ template_name = "blog/index.html" context_object_name = "article_list" def get_queryset(self): """ 重寫 get_queryset 方法,取出發表的文章並轉換文章格式 """ article_list = Article.objects.filter(status='p') for article in article_list: article.body = markdown2.markdown(article.body, extras=['fenced-code-blocks'], ) return article_list def get_context_data(self, **kwargs): kwargs['category_list'] = Category.objects.all().order_by('name') return super(IndexView, self).get_context_data(**kwargs)
此次重寫了 get_context_data
方法,這個方法是用來添加額外的內容傳遞到模板文件的上下文對象(context)中。上面的例子中將 category_list
添加到上下文變量中,則在模板中可以使用 {{ }} 來展示 category_list
中的內容。
ListView
主要用來獲取某個model
中的所有數據,通過template_name
屬性來指定需要渲染的模板,通過context_object_name
屬性來指定上下文變量(默認為object_list
),通過重寫get_queryset
方法來對model
中的數據增加其他邏輯,通過重寫get_context_data
方法來為上下文對象添加額外的對象。
DetailView
ListView
用來獲取某個 model
中的所有數據,而 DetailView
則是獲取每個數據的詳細信息,比如 ListView
獲取所有文章列表,DetailView
用來獲取文章的詳細信息。
class ArticleDetailView(DetailView): """ 文章詳情頁 """ model = Article template_name = 'blog/detail.html' context_object_name = "article" # 在 urlpattern 中定義的 pk_url_kwarg = 'article_id' def get_object(self, queryset=None): """ 獲取對應文章的信息 """ obj = super(ArticleDetailView, self).get_object() obj.body = markdown2.markdown(obj.body, extras=['fenced-code-blocks'], ) return obj # 增加 form 到 context def get_context_data(self, **kwargs): kwargs['comment_list'] = self.object.blogcomment_set.all() #獲取評論 return super(ArticleDetailView, self).get_context_data(**kwargs)
pk_url_kwarg
定義用來獲取對應的單條數據,需要傳遞主鍵的值。get_object
方法獲取 pk_url_kwarg
中所要查找的對象,類似於 ListView
中的 get_queryset
方法,get_context_data
方法和 ListView
中的功能相同。
DetailView
主要用在獲取某個model
的單個對象中,需要在URL
中傳遞一個主鍵值進行查詢。
作者:田飛雨
鏈接:https://www.jianshu.com/p/6d6c890f5f72
來源:簡書