基于类的视图简介

Posted crazy-zjl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于类的视图简介相关的知识,希望对你有一定的参考价值。

使用基于类的视图

本质上,基于类的视图允许您使用不同的类实例方法响应不同的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/

以上是关于基于类的视图简介的主要内容,如果未能解决你的问题,请参考以下文章

基于 Django 类的视图:了解视图类中的参数

基于Django类的视图:发布表单数据返回302 Found状态代码

SpringCloud系列十一:SpringCloudStream(SpringCloudStream 简介创建消息生产者创建消息消费者自定义消息通道分组与持久化设置 RoutingKey)(代码片段

如何在 django 中使用基于类的视图

django-基于类的视图

如何将 View 类中的代码片段移动到 OnAppearing() 方法?