基於類的檢視簡介
使用基於類的檢視
本質上,基於類的檢視允許您使用不同的類例項方法響應不同的HTTP請求方法,而不是在單個檢視函式中通過 if 邏輯來判斷使用不同的程式碼來處理。
在檢視函式中處理HTTP請求:
from django.http import HttpResponse def my_view(request): if request.method == 'GET': # <view logic> return HttpResponse('result') View Code
在基於類的檢視中:
from django.http import HttpResponse from django.views import View class MyView(View): def get(self, request): # <view logic> return HttpResponse('result') View Code
因為Django的URL解析器希望將請求和相關引數傳送給一個可呼叫的函式,而不是一個類,所以基於類的檢視有一個as_view()類方法,它返回一個函式,當一個匹配相關模式的URL的請求到達時,可以呼叫這個函式。
函式建立類的例項並呼叫其
dispatch()
方法。 dispatch
檢視請求以確定它是否是GET、POST等,如果定義了匹配的方法,則將請求轉發給匹配的方法,如果沒有,則提出HttpResponseNotAllowed:
# urls.py from django.urls import path from myapp.views import MyView urlpatterns = [ path('about/', MyView.as_view()), ]
雖然很小的基於類的檢視不需要任何類屬性來執行其工作,但是類屬性在許多基於類的設計中非常有用,並且有兩種方法來配置或設定類屬性。
第一種是標準的Python方法,它對子類中的屬性和方法進行子類化和重寫。如果你的父類有這樣的屬性問候語
from django.http import HttpResponse from django.views import View class GreetingView(View): greeting = "Good Day" def get(self, request): return HttpResponse(self.greeting) View Code
在子類裡可以重寫它:
class MorningGreetingView(GreetingView): greeting = "Morning to ya"
另一個選選擇是將類屬性配置為URLconf中as_view()呼叫的關鍵字引數:
urlpatterns = [ path('about/', GreetingView.as_view(greeting="G'day")), ]
使用基於類的檢視處理表單
在基於函式的檢視中處理表單:
from django.http import HttpResponseRedirect from django.shortcuts import render from .forms import MyForm def myview(request): if request.method == "POST": form = MyForm(request.POST) if form.is_valid(): # <process form cleaned data> return HttpResponseRedirect('/success/') else: form = MyForm(initial={'key': 'value'}) return render(request, 'form_template.html', {'form': form}) View Code
在基於類的檢視中處理表單:
from django.http import HttpResponseRedirect from django.shortcuts import render from django.views import View from .forms import MyForm class MyFormView(View): form_class = MyForm initial = {'key': 'value'} template_name = 'form_template.html' def get(self, request, *args, **kwargs): form = self.form_class(initial=self.initial) return render(request, self.template_name, {'form': form}) def post(self, request, *args, **kwargs): form = self.form_class(request.POST) if form.is_valid(): # <process form cleaned data> return HttpResponseRedirect('/success/') return render(request, self.template_name, {'form': form}) View Code
這是一個非常簡單的例子,但是您可以看到,您可以通過覆蓋任何類屬性(例如form_class,通過URLconf配置),或者子類化和覆蓋一個或多個方法(或者兩者都覆蓋!)來定製這個檢視。
裝飾基於類的檢視
在URLconf中裝飾
裝飾基於類的檢視的最簡單方法是裝飾
as_view()
方法的結果。最簡單的方法是在URLconf中部署檢視:
from django.contrib.auth.decorators import login_required, permission_required from django.views.generic import TemplateView from .views import VoteView urlpatterns = [ #給檢視所有方法加上 login_required 裝飾器 path('about/', login_required(TemplateView.as_view(template_name="secret.html"))), path('vote/', permission_required('polls.can_vote')(VoteView.as_view())), ] View Code
這種方法在每個例項的基礎上應用裝飾器。如果希望裝飾檢視的每個例項,則需要採用不同的方法。
裝飾class
為了裝飾以類為基礎的檢視的每個例項,您需要裝飾類定義本身。要做到這一點,您將裝飾器應用於類的
dispatch()
方法。
類上的方法與獨立函式並不完全相同 ,因此您不能僅對方法應用函式修飾符—您需要首先將其轉換為方法修飾符。method_decorator裝飾器將函式裝飾器轉換為方法裝飾器,以便可以在例項方法上使用它。例如:
from django.contrib.auth.decorators import login_required from django.utils.decorators import method_decorator from django.views.generic import TemplateView class ProtectedView(TemplateView): template_name = 'secret.html' #將函式裝飾器 login_required 轉換為方法裝飾器 @method_decorator(login_required) def dispatch(self, *args, **kwargs): return super().dispatch(*args, **kwargs) View Code
或者,更簡潔地說,您可以修飾類,並將要修飾的方法的名稱作為關鍵字引數名傳遞:
@method_decorator(login_required, name='dispatch') class ProtectedView(TemplateView): template_name = 'secret.html'
如果您在幾個地方使用了一組公共裝飾器,那麼您可以定義一個裝飾器列表或元組,並使用它而不是多次呼叫method_decorator()。下面兩個類是等價的:
decorators = [never_cache, login_required] @method_decorator(decorators, name='dispatch') class ProtectedView(TemplateView): template_name = 'secret.html' @method_decorator(never_cache, name='dispatch') @method_decorator(login_required, name='dispatch') class ProtectedView(TemplateView): template_name = 'secret.html' View Code
裝飾器將按照傳遞給裝飾器的順序處理請求。在本例中,never_cache()
將在 login_required()
之前處理請求。
在本例中,ProtectedView
的每個例項都有登入保護
學習自用,歡迎大神評論、指正
詳情見Django文件:
https://docs.djangoproject.com/zh-hans/2.1/topics/class-based-views/intro/