• 基于类的视图简介


    使用基于类的视图

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

  • 相关阅读:
    Python+Selenium 自动化实现实例Xpath捕捉元素的几种方法
    Python+Selenium 自动化实现实例获取页面元素信息(百度首页)
    Example4_6(用类名调用类方法)
    Example5_2(子类对象的构造方法)
    关键字super
    字符数组中的大小写字母变换/使用对象数组
    参数传值(Example4_7.Example4_8,Example4_9)
    私有变量和私有方法(Example4_15和Example4_16)
    Example4_11(关键字this)
    成员变量(对象共享类变量及常量的用法)Example4_4//Example4_5
  • 原文地址:https://www.cnblogs.com/crazy-zjl/p/10324994.html
Copyright © 2020-2023  润新知