视图的任务
视图负责接受一个 HttpRequest,并返回 HttpResponse 或 抛出异常(Http404)
视图的实现
视图可以是一个函数
def index(reqest):
# ....
视图可以是一个类
class IndexView(ListView):
model = Author
当通过类实现,.as_view()
为类视图提供一个函数入口(function-like entry)
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
]
使用类视图的两种方式
URLConf
# 通过将 kwargs 传给 .as_view() 覆盖类中的属性
# 例子:重定向到首页
from django.views.generic.base import RedirectView
urlpatterns = [
path('redirect-to-index', TemplateView.as_view(url="/")),
]
继承
# 通过继承修改属性/方法
from django.views.generic import TemplateView
class AboutView(TemplateView):
template_name = "about.html"
类视图处理流程
在 URLConf 匹配 --> 调用相应的视图 .view_as()
--> 调用类视图中的 .dispatch()
决定 Http 请求方法 --> 调用相应的类方法 get()
, post()
, head()
# 下面代码证明 类视图 支持 http head 请求方法
# 如果请求是 http get 方法,Django 返回 Listview 已经帮我们实现的 get()
# 如果请求时 http head 方法, Django 返回一个 头部带有 'Last-Modified' ,body 是空的响应,决定是否进行 http get 请求,下载全部书目
from django.http import HttpResponse
from django.views.generic import ListView
from books.models import Book
class BookListView(ListView):
model = Book
def head(self, *args, **kwargs):
last_book = self.get_queryset().latest('publication_date')
response = HttpResponse('')
# RFC 1123 date format
response['Last-Modified'] = last_book.publication_date.strftime('%a, %d %b %Y %H:%M:%S GMT')
return response
1. Class-based Views
类视图并不是要替换函数视图,但是类视图可以简化代码和实现代码复用
装饰类视图
2种方式
装饰 .as_view()
from django.contrib.auth.decorators import login_required, permission_required
from django.views.generic import TemplateView
from .views import VoteView
urlpatterns = [
path('about/', login_required(TemplateView.as_view(template_name="secret.html"))),
# 下面是因为 permission_required 本身返回一个函数,即变成 returned_func(VoteView.as_view())
path('vote/', permission_required('polls.can_vote')(VoteView.as_view())),
]
装饰 .dispatch()
装饰 .dispatch()
, 但(函数)装饰器要先用 method_decorator()
转换成方法装饰器
from django.utils.decorators import method_decorator
# 装饰 dispatch()
@method_decorator(login_required, name='dispatch')
class ProtectedView(TemplateView):
template_name = 'secret.html'
# 按顺序使用两个装饰器
decorators = [never_cache, login_required]
@method_decorator(decorators, name='dispatch')
class ProtectedView(TemplateView):
template_name = 'secret.html'
Class-based Views -- Intro
使用 Class-based Views
类视图使用方法 .get()
, .post()
, .head()
等响应不同的 Http 请求
函数视图使用 if request.method == 'POST'
判断
from django.http import HttpResponse
from django.views import View
class MyView(View):
def get(self, request):
#
return HttpResponse('result')
通用视图介绍 Generic Views
Base Views
View
-
RedirectView
:属性url
# 重定向到该地址 -
TemplateView
:属性template_name
# 指定渲染的模板
View
View 是最基础的类视图,通常用于被其他视图继承
任务:
.as_view()
: 提供函数接口;生成 self.request
; 从 URL 中生成 self.args
, self.kwargs
.dispatch()
:决定调用哪个方法(.get()
, .post()
...) 响应请求
RedirectView
属性:
-
url
: 重定向到该地址 -
pattern_name
: 类似 django.urls.reverse,传递该类接受的self.args
,self.kwargs
-
permanent
:True
/False
默认:False -
query_string
:True
/False
是否将该类接收到的 query_string(?next=home&id=1)接到 url 后面,默认:False
方法:
get_redirect_url(*args, **kwargs)
:返回重定向的 URL
默认实现:根据 query_string 生成 url
- 返回
url
- 根据
pattern_name
返回 url
例子:
# 更新计数器,并重定向
def get_redirect_url(self, *args, **kwargs):
article = get_object_or_404(Article, pk=kwargs['pk'])
article.update_counter()
return super().get_redirect_url(*args, **kwargs)
RedirectView
TemplateView
重要属性:
-
extra_context
:添加简单的 context 到模板
TemplateView.as_view(extra_context={'title': 'Custom Title'})
-
template_name [get_template_names()]
:指定要使用的模板
重要方法:
-
get_context_data()
: 返回一个字典(包含模板要用的 context)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['number'] = random.randrange(1, 100)
return context
TemplateView
Form View
使用类视图的好处:可以简单修改属性(.as_view(form_class=OtherForm)
),并重用其他逻辑
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():
#
return HttpResponseRedirect('/success/')
return render(request, self.template_name, {'form': form})
Mixin
Mixin 是一种多继承的形式
Django 提供多种 mixin 类,命名以 Mixin
结尾
Minix 类提供单一的功能,一些通用视图是通过继承多个 Mixin,然后进行适当地修改而来的
限制:继承时,只能继承一个通用视图,其他都应该是 Mixin