基於類的視圖簡介
使用基於類的視圖
本質上,基於類的視圖允許您使用不同的類實例方法響應不同的HTTP請求方法,而不是在單個視圖函數中通過 if 邏輯來判斷使用不同的代碼來處理。
在視圖函數中處理HTTP請求:
from django.http import HttpResponse def my_view(request): if request.method == ‘GET‘: # <view logic> return HttpResponse(‘result‘)View Code
在基於類的視圖中:
fromView Codedjango.http import HttpResponse from django.views import View class MyView(View): def get(self, request): # <view logic> return HttpResponse(‘result‘)
因為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/
基於類的視圖簡介