Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

基于类的视图简介

Crazy丶土豆 2019-01-26 21:45:00 阅读数:155 评论数:0 点赞数:0 收藏数:0

使用基于类的视图

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

版权声明
本文为[Crazy丶土豆]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/crazy-zjl/p/10324994.html

编程之旅,人生之路,不止于编程,还有诗和远方。
阅代码原理,看框架知识,学企业实践;
赏诗词,读日记,踏人生之路,观世界之行;

支付宝红包,每日可领