1. 程式人生 > >基於類的視圖簡介

基於類的視圖簡介

分享 關鍵字 -a .py decorator spl docs 有用 ews

使用基於類的視圖

本質上,基於類的視圖允許您使用不同的類實例方法響應不同的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/

基於類的視圖簡介