1. 程式人生 > >Django 1.6 基於類的通用檢視

Django 1.6 基於類的通用檢視

最初 django 的檢視都是用函式實現的,後來開發出一些通用檢視函式,以取代某些常見的重複性程式碼。通用檢視就像是一些封裝好的處理器,使用它們的時候只須要給出特定的引數集即可,不必關心具體的實現。各種通用檢視的參考參見:https://docs.djangoproject.com/en/1.6/ref/class-based-views/

然後函式式檢視的缺點——難以擴充套件和自定義,開始顯現出來。於是 1.3 起 django 開始用類檢視來實現通用檢視。較於函式,類能夠更方便的實現繼承和 mixins。但類檢視並非要取代函式檢視,這從現在 URLConf 仍然保留著函式式的呼叫方式便可以看出來。

因為 URLConf 仍然使用“給一個可呼叫物件傳入 HttpRequest ,並期待其返回一個 HttpResponse”這樣的邏輯,所以對於類檢視,必須設計一個可呼叫的介面。這就是類檢視的 as_view() 類方法

。他接受 request,並例項化類檢視,接著呼叫例項的 dispatch() 方法。這個方法會依據 request 的請求型別再去呼叫例項的對應同名方法,並把 request 傳過去,如果沒有對應的方法,就引發一個 HttpResponseNotAllowed 異常。(可以捕捉這個異常用以返回一個 404)值得注意的是,這個(比如 get)方法的返回值和普通的檢視函式的返回值沒有什麼不同,這意味著,http shortcuts(render_to_response之類的)和 TemplateResponse 在類視圖裡也是有效的。

django 提供了一系列現成的類檢視,他們都繼承自一個 View 基類(django.views.generic.base.View)。在這個基類裡實現了與 URLs 的介面(as_view)、請求方法匹配(dispatch)和一些其他的基本功能。比如 RedirectView 實現了一個簡單的 HTTP 重定向,TemplateView 給 View 添加了一個渲染模板的功能。

簡單用法:

最簡單的通用檢視用法就是直接在 URLConf 裡建立他們。如果你只需要改幾個類檢視的屬性的話,你可以直接把他們當做關鍵字引數傳入檢視的 as_view() 方法裡。任何傳入 as_view() 的引數都會覆蓋類檢視例項裡的同名屬性。

from django.conf.urls import patterns from django.views.generic import TemplateView urlpatterns = patterns('', (r'^about/', TemplateView.as_view(template_name="about.html
")), )

子類化通用檢視:

一種稍微高階點的使用通用檢視的方法是子類化他們,並重寫必要的屬性(比如 template_name)和方法(比如 get_context_data)。舉個栗子,一個 AboutView,他覆蓋了 TemplateView 的模板屬性和獲取 Context 方法(這是使用 TemplateView 的一般做法):

# some_app/views.pyfrom django.views.generic import TemplateView class AboutView(TemplateView): template_name ="about.html"def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) #alter context return context

對應的 URLConf:

# urls.pyfrom django.conf.urls import patterns from some_app.views import AboutView urlpatterns = patterns('', (r'^about/', AboutView.as_view()), )

這裡的 get_context_data(self,**kwargs) 方法只接受關鍵字引數,是因為這個引數來自於 URLConf 的第三個引數(這例子裡沒用到),而這個引數就是一個關鍵字引數。

另外,如果想要對 context 做某些額外的處理,比如增加一些變數,那麼就應該把程式碼寫在呼叫了父類的 get_context_data 之後,return context 之前。

上面這個例子對通用檢視的好處體現的還不明顯(TemplateView 比 render_to_response 強不到哪去),通用檢視的優勢常常體現在對資料庫的訪問上,比如下面這個 顯示物件列表的檢視,完全省去了對資料庫的操作:

# views.pyfrom django.views.generic import ListView from books.models import Publisher class PublisherList(ListView): model = Publisher # urls.pyfrom django.conf.urls import patterns, url from books.views import PublisherList urlpatterns = patterns('', url(r'^publishers/$', PublisherList.as_view()), )

ListView 會用到的模板:

{% extends "base.html"%} {% block content %} <h2>Publishers</h2><ul> {%for publisher in object_list %} <li>{{ publisher.name }}</li> {% endfor %} </ul> {% endblock %}

template contexts 的變數名匹配:

上例中,在 publisher_list.html 模板中使用的 context 變數名為“object_list”。這是一個通用名,即 ListView 檢視總會使用的一個名字,另外當你訪問的是一個數據庫模型的時候,比如上例中的 Publisher,檢視還會自動用小寫的模型名+_list 的格式命名一個相同的 context 去渲染模板,即“publisher_list”。所以上例中和其他對模型的訪問都可以用這種格式的名字來編寫模板。如果對此種匹配方式仍不放心,還可以在通用檢視中顯式指定 context 的名字,就像這樣(建議總是顯示指定):

# views.pyfrom django.views.generic import ListView from books.models import Publisher class PublisherList(ListView): model = Publisher context_object_name ='my_favourite_publishers'

對資料模型進行篩選:

通過 model = Publisher 這樣的方式可以指定通用檢視使用的模型,而當想要對模型的 objects 管理器應用 filter 的時候,可以通過 query_set 變數來指定:

from django.views.generic import ListView from books.models import Book class BookList(ListView): queryset = Book.objects.order_by('-publication_date') context_object_name ='book_list'

而如果 filter 的引數來自於 url 匹配出的子組,那麼這個引數將被傳入類檢視的 self.args 和 self.kwargs 屬性內。get_queryset() 方法也可以用來做邏輯性更強的定製:

# urls.pyfrom django.conf.urls import patterns from books.views import PublisherBookList urlpatterns = patterns('', (r'^books/([\w-]+)/$', PublisherBookList.as_view()), ) # views.pyfrom django.shortcuts import get_object_or_404 from django.views.generic import ListView from books.models import Book, Publisher class PublisherBookList(ListView): template_name ='books/books_by_publisher.html'def get_queryset(self): self.publisher = get_object_or_404(Publisher, name=self.args[0]) return Book.objects.filter(publisher=self.publisher)

實現模型訪問時的額外小動作:

如果想要在對資料庫進行訪問之前(或後)實現一些額外的操作,那麼可以通過封裝 類檢視的 get_object() 方法來實現。

例:假設 Author 模型有一個 DateTimeField 型別的欄位,名為 last_accessed,用以儲存最後一次被訪問的時間。

# models.pyfrom django.db import models class Author(models.Model): salutation = models.CharField(max_length=10) name = models.CharField(max_length=200) email = models.EmailField() headshot = models.ImageField(upload_to='author_headshots') last_accessed = models.DateTimeField() #URLConffrom django.conf.urls import patterns, url from books.views import AuthorDetailView urlpatterns = patterns('', #... url(r'^authors/(?P<pk>\d+)/$', AuthorDetailView.as_view(), name='author-detail'), ) #Viewfrom django.views.generic import DetailView from django.utils import timezone from books.models import Author class AuthorDetailView(DetailView): queryset = Author.objects.all() def get_object(self): # Call the superclass object = super(AuthorDetailView, self).get_object() # Record the last accessed date object.last_accessed = timezone.now() object.save() # Return the objectreturn object

此處 URL 裡的 pk 是 DetailView 檢視預設使用的某個名字,詳情可參考檢視的細節頁面。

對 HTTP require method 的支援:

為不同的請求寫一個同名的方法就可以了,呼叫工作會有 dispatch() 方法來做。比如:

# urls.pyfrom django.conf.urls import patterns from myapp.views import MyView urlpatterns = patterns('', (r'^about/', MyView.as_view()), ) from django.http import HttpResponse from django.views.generic import View class MyView(View): def get(self, request): # <view logic>return HttpResponse('result')

還可以定義一些 head() , post() 之類的方法。這種方式取代了檢視函式裡的 if 分支邏輯。

處理 Form:

基本 Forms:

一個簡單的 contact form

# forms.pyfrom django import forms class ContactForm(forms.Form): name = forms.CharField() message = forms.CharField(widget=forms.Textarea) def send_email(self): # 使用 self.cleaned_data 字典來發送一封郵件pass

對應的檢視可以使用 FormView 構建:

# views.pyfrom myapp.forms import ContactForm from django.views.generic.edit import FormView class ContactView(FormView): template_name ='contact.html' form_class = ContactForm success_url ='/thanks/'def form_valid(self, form): # 當有效的資料被 POST 進來以後,本方法就會被呼叫# 本方法應當返回一個 HttpResponse. form.send_email() return super(ContactView, self).form_valid(form)

注意:

  • FormView 繼承自 TemplateResponseMixin,所以 template_name 屬性可用
  • form_valid() 的預設實現僅僅是將頁面重定向至 success_url

相關推薦

Django 1.6 基於通用檢視

最初 django 的檢視都是用函式實現的,後來開發出一些通用檢視函式,以取代某些常見的重複性程式碼。通用檢視就像是一些封裝好的處理器,使用它們的時候只須要給出特定的引數集即可,不必關心具體的實現。各種通用檢視的參考參見:https://docs.djangoproject.com/en/1.6/ref/c

Django 中針對基於檢視新增 csrf_exempt

在Django中對於基於函式的檢視我們可以 @csrf_exempt 註解來標識一個檢視可以被跨域訪問。那麼對於基於類的檢視,我們應該怎麼辦呢? 簡單來說可以有兩種訪問來解決 方法一:在類的 d

Django-深度分析Django基於檢視(1)(翻譯)

時間有限,只能簡單翻譯,略去一些無關緊要的細節。 本文是基於Django1.5版的,但是原理分析依舊非常有意義。 什麼是基於類的檢視?(CBV) Django類也就是Python類。一個Django檢視就是就是用來處理HTTP請求並返回HTTP響應的一段程式碼。不多不少

學習筆記-Python-Django-session、paginator、基於檢視、admin

# session - 為了應對HTTP協議的無狀態性 - 用來儲存使用者比較敏感的資訊 - 屬於request的一個屬性 - 常用操作: - request.session.get(key, defaultValue) - request.se

Django編寫RESTful API(三):基於檢視

歡迎訪問我的個人網站:www.comingnext.cn 前言 在上一篇文章中,主要講的是請求和響應,專案裡面views.py中的檢視函式都是基於函式的,並且我們介紹了@api_view這個很有用的裝飾器。同時,我們還介紹了APIView這個類,但是還沒使用它。在這篇文章中

django--基於檢視

Django 提供基本的檢視類,它們適用於絕大多數的應用。所有的檢視類繼承自View 類,它負責將檢視連線到URL、HTTP 方法排程和其它簡單的功能。 在urlconf中的簡單用法: 使用通用檢視最簡單的方法是直接在URLconf 中建立它們。如果你只是修改基於類的檢

Django REST framework教程三: 基於檢視

教程索引目錄 Django REST framework的系列教程 對於需要通篇瞭解的同學,可以點選教程索引目錄。 其實,與其使用基於方法(function based)的檢視,我們更加傾向使用基於類(class based)的檢視。接下來,你將看到這

1.6 序列的通用操作

blog sar 重復 color 統計 序列值 end 切片 list() 下面幾個小節分別會介紹到的list、tuple、str等都屬於序列。 先介紹序列通用操作,序列的通用操作部分對list、tuple、str都適用,此處以list為例進行演示。 在講序列的通用操作之

Django2基於檢視詳解

一、基本檢視     view     TemplateView     RedirectView 二、通用顯示檢視     DetailView     ListView 三、通用編輯檢視

Django 1.6 Test Driven Development

Last Updated: 01/29/2014 - updated code for the form (thanks vic!) 12/29/2013 - restructured entire blog post Test Driven Development (TDD) is an ite

Transaction Management with Django 1.6 – Real Python

If you ever devoted much time to Django database transaction management, you know how confusing it can get. In the past, the documentation provided quit

Django第十二篇-----通用檢視

    什麼是通用檢視 通用檢視把檢視開發中常用的寫法和模式抽象出來,讓你編寫少量程式碼就能快速實現常見的資料檢視。顯示物件列表就是這樣一種任務 有了通用檢視,可以把模型作為額外的引數傳給 URL 配置。Django 自帶的通用檢視能實現下述功能: • 列出物

Spark MLlib 1.6 -- 聚

聚類是根據某種相似度量,將‘相似’的樣本劃分到同一個子類中,所以聚類是一種無監督學習。聚類常用於探索分析,或(和)看作分層監督學習管道上一個環節(在這個管道上,對每個聚類結果再深入進行分類或迴歸)。 Spark.mllib包支援以下模型: 1.1  K-mea

Django筆記 自定義ListView通用檢視

資料 自定義get_queryset函式 class Browse(generic.ListView): template_name = 'app/browse.html'

Django基於的編輯檢視和Mixins

== 內建的基於類的通用編輯檢視 (Forms) 表單(處理)通常包含3條路徑: * 初始的GET (空或預填充的表單) * 非法資料的POST (通常重新顯示錶單並提示錯誤) * 合法資料的POST (處理資料並通常重定向) 你自己實現這些常常需要重複很多模式化的程式碼。

Django-restframework04 基於檢視檢視函式

1. 基於類的檢視函式(views.py) from snippets.models import Snippet from snippets.serializers import SnippetSerializer from django.http im

[options] 未與 -source 1.6 一起設置引導路徑

除maven cas 項目 報錯 失敗 build.xml 查看 version dia 用ant與eclipse編譯Cassandra 1.2.19,出現了“ [options] 未與 -source1.6一起設置引導類路徑”的警告,並出現了一些編譯錯誤,提示編譯失敗,上

spring boot1.5.6 測試1

sts mediatype perf app example contex amp form turn package com.example.demo;import org.junit.Before;import org.junit.Test; import org.ju

Django Series - 01】以前用 1.6.11,最近用 1.10.8,現在又想換最新版本 2.1.2(探索中...)

Django Series(Django2.1.2 + Anaconda3) (一)安裝並配置 Django 環境 ||| 基於 Django 進行 Web 開發 (二)Django 基礎知識:語法、教程 (三)使用者管理模組:建立使用者、登入、退出 (四)資料的增刪改:使用者提交資

Django 實現HTML轉PDF 用通用檢視編寫PDF 並且讓PDF支援中文

Django 實現HTML轉PDF 用通用檢視編寫PDF 並且讓PDF支援中文 如何使用django-easy-pdf django-easy-pdf的依賴 安裝django-easy-pdf 使用過程中遇到的問題總結