在Django1.3以前,通用視圖是以函數的方式來實現的。基於函數的實現已經不 建議使用,建議使用這裏介紹的基於類的實現方式。 html
基於類的通用視圖(以及任何繼承了Django提供的基礎類的基於類的視圖)都可以如下面兩種方式被配置:子類化,或者直接經過URLconf來傳遞參數。 web
當你子類化一個類視圖時,你能夠重寫一些屬性(好比template_name)或者 一些方法(好比 get_context_data)在你的子類中來提供一些新的值或者方 法。考慮一下,好比,一個僅僅須要展現一個模板的視圖,about.html。Django有一個通用視圖來完成這個功能 - TemplateView - 所以你能夠子類化它,而後重寫模板的名稱: 數據庫
# some_app/views.py from django.views.generic import TemplateView class AboutView(TemplateView): template_name = "about.html"
這時,你只須要添加這個新的視圖到你的URLconf配置中。由於類視圖自己是一個類,我 們把URL指向 as_view 這個類方法來替代類自己,這是類視圖的入口點: django
# urls.py from django.conf.urls import patterns, url, include from some_app.views import AboutView urlpatterns = patterns('', (r'^about/', AboutView.as_view()),)
做爲一個選擇,若是你僅僅修改類視圖中少許簡單的屬性,你能夠直接傳遞新的屬性 到類自己調用 as_view 方法中: app
from django.conf.urls import patterns, url, include from django.views.generic import TemplateView urlpatterns = patterns('', (r'^about/', TemplateView.as_view(template_name="about.html")),)
一個相似的重寫模式能夠用在 RedirectView 的 url 屬性上,這是另一個簡單的通用視圖。 函數
若是要深刻理解class-based view, 那首先就要了解什麼是Mixin! Django把基本的http請求和響應抽象出來, 封裝成各自的類, 在使用過程當中只需把各個基類聚合到一塊兒使用, 並按照本身的要求重寫本身須要的方法就能夠了, 那麼就把這些基類叫Mixin吧. 在Django中比較基礎的Mixin主要有幾類: url
View(視圖基礎類) spa
SingleObjectMixin(單對象類) 設計
MultipleObjectMixin(多對象類) code
TemplateResponseMixin(模板響應類)
FormMixin(表單類)
YearMixin, MonthMixin, DayMixin, WeekMixin, DateMixin(幾個基於時間關係的類)
其餘的全部內置class-based view都是把以上幾個基礎類組合, 重寫方法以達到預期的結果. 好比DetailView這個類就組合了SingleObjectTemplateResponseMixin和BaseDetailView.
TemplateView確實頗有用,可是你可能須要把數據庫中的內容查詢展現出來,不要緊,Django一樣提供了大把內置的通用視圖。下面看一個簡單例子:
# models.py from django.db import models class Publisher(models.Model): name = models.CharField(max_length=30) address = models.CharField(max_length=50) city = models.CharField(max_length=60) state_province = models.CharField(max_length=30) country = models.CharField(max_length=50) website = models.URLField() class Meta: ordering = ["-name"] def __unicode__(self): return self.nameclass Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField('Author') publisher = models.ForeignKey(Publisher) publication_date = models.DateField()
爲了給全部的Publisher創建一個列表頁,咱們將按照這樣的方式來配置URLconf:
from django.conf.urls import patterns, url, include from django.views.generic import ListView from books.models import Publisher urlpatterns = patterns('', (r'^publishers/$', ListView.as_view( model=Publisher,template_name=’publisher_list.html‘, )),)
下面是簡單的模板實例:
{% extends "base.html" %} {% block content %} <h2>Publishers</h2> <ul> {% for publisher in object_list %} <li>{{ publisher.name }}</li> {% endfor %} </ul> {% endblock %}
使用通用視圖能夠極大的提升開發速度。然而,在大多時候咱們會發現通用視圖沒法知足需求。爲此,咱們能夠對通用視圖進行擴展來增長本身的功能。擴展通用視圖的方法是子類化它們,而且重寫它們的屬性或者方法。
默認狀況下,通用視圖將全部相關Model的查詢到的對象放到object_list變量中,這雖然能正常工做,可是對模板設計者不友好。
通用視圖中的這個屬性 : context_object_name指定上下文(context)變量要使用的名字。在這個例子中咱們在URLconf中重寫了它,由於這只是簡單的修改:
urlpatterns = patterns('', (r'^publishers/$', ListView.as_view( model=Publisher, template_name=」publisher_list.html「, context_object_name="publisher_list", )),)
咱們應該使用context_object_name來指定上下文(context)變量。
咱們可能須要一些通用視圖沒有提供的額外信息,咱們能夠子類化DetailView而後提供你本身的 get_context_data方法的實現。
DetailView 中默認的實現只是簡單的 給模板添加了要展現的對象,可是你這能夠這麼重寫來展現更多信息:
from django.views.generic import DetailView from books.models import Publisher, Book class PublisherDetailView(DetailView): context_object_name = "publisher" model = Publisher def get_context_data(self, **kwargs): # Call the base implementation first to get a context context = super(PublisherDetailView, self).get_context_data(**kwargs) # Add in a QuerySet of all the books context['book_list'] = Book.objects.all() return context
model參數指定了視圖(view)在哪一個數據庫模型之上進行操做,可是這個太不靈活了,咱們可使用 queryset參數來指定一個對象列表:
from django.views.generic import DetailView from books.models import Publisher, Book class PublisherDetailView(DetailView): context_object_name = "publisher" queryset = Publisher.objects.all()
指明model = Publisher 等價於快速聲明的queryset = Publisher.objects.all() 。然而,使用 queryset能夠定義一個過濾的對象列表:
from django.views.generic import ListView from books.models import Book class AcmeBookListView(ListView): context_object_name = "book_list" queryset = Book.objects.filter(publisher__name="Acme Publishing") template_name = "books/acme_list.html"
另外一個廣泛的需求是在給定的列表頁面中根據URL中的關鍵字來過濾對象。ListView 有一個 get_queryset() 方法來供咱們重寫。
這裏,咱們有一個URLconf定義了一組供捕獲的參數:
from books.views import PublisherBookListView urlpatterns = patterns('', (r'^books/(\w+)/$', PublisherBookListView.as_view()),)
下一個,咱們定義了 PublisherBookListView 視圖:
from django.shortcuts import get_object_or_404 from django.views.generic import ListView from books.models import Book, Publisher class PublisherBookListView(ListView): context_object_name = "book_list" template_name = "books/books_by_publisher.html" def get_queryset(self): publisher = get_object_or_404(Publisher, name__iexact=self.args[0]) return Book.objects.filter(publisher=publisher)
http://django-14-tkliuxing.readthedocs.org/en/latest/topics/class-based-views.html
http://simple-is-better.com/news/643
http://simple-is-better.com/news/644