上篇我们介绍 URLs 时留下了 Views 的坑没填,没办法,Views 作为整个 Django 框架的核心,跟很多模板都深刻绑定在一起
本篇就来介绍这个重中之重:Views
1. 类视图和函数视图
之前留下了 IndexView、DetailView、ResultsView、vote 没写
as_view() 代表前三个是类视图,第四个 vote 是函数视图,视图就是用来实现业务功能的模块,选用类视图还是函数视图视情况而定,一般显示内容的选用类视图,实现功能的选用函数视图, IndexView 显示问题索引、DetailView 显示问题内容、ResultsView 显示投票结果,都属于显示内容,所以选用类视图。vote 实现投票功能,所以选用函数视图
2. 函数视图
(1)通过函数名绑定 url
(2)自己编写,第一个参数 request 是固定且必要的,第二个参数是 url 里的参数 ( '< >' 里包裹的)
(3)必须返回一个 HttpResponse 对象或者 Http404,404 是啥不用多说了
而对于类视图,一般我们能使用通用视图时,优先使用通用视图,下面先说什么是通用视图
3. 通用视图:
(1)属于类视图
(2)由 Django 提供 ,使用 from django.views import generic 导入
(3)类视图自动实现了很多功能,比如自动返回 HttpResponse 对象,为我们能节省很多代码和精力,但我们需要学会类视图的使用,官方链接:https://docs.djangoproject.com/zh-hans/2.1/topics/class-based-views/
(4)用类名绑定 url、用 model 属性绑定数据模型, 用 template_name 属性绑定页面模板,从而实现对个模块的关联,注意每个类必须继承通用视图类 generic 的一个子类
4. 编写 IndexView、DetailView、ResultsView、vote
from django.shortcuts import render # Create your views here. # 导入通用视图 from django.views import generic # 导入要用到的数据模型 from .models import Question, Choice # 导入时区模块 from django.utils import timezone # 导入自动生成404的快捷函数,生成HttpResponse对象的快捷函数 from django.shortcuts import get_object_or_404, render # 导入页面重定向模块 from django.http import HttpResponseRedirect # 导入反向解析函数 from django.urls import reverse # 创建索引视图 # 必须继承字generic的一个子类,这样才能自动实现一些功能 # 类名直接对应urls.py里path()的第二个参数 # 也就是URLs和Views是通过类名或者函数名进行区别绑定的 class IndexView(generic.ListView): # model属性绑定数据模型 model = Question # template_name属性绑定页面模板 template_name = 'polls/index.html' # context_object_name 用于对传给页面模板的变量进行命名 context_object_name = 'question_list' # 创建问题详情视图 class DetailView(generic.DetailView): model = Question template_name = 'polls/detail.html' # get_queryset()用于筛选model得到数据,结果返回给model def get_queryset(self): # 返回出版时间小于现在的 # Question.objects.filter(pub_date__lte=timezone.now()) # 是Django提供的数据库API的写法 return Question.objects.filter(pub_date__lte=timezone.now()) # 创建投票结果视图 class ResultsView(generic.DetailView): model = Question template_name = 'polls/results.html' # 创建投票功能视图,是函数视图,实现投票业务 def vote(request, question_id): # 获取主键pk等于参数question_id的Question # get_object_or_404()实现:要么获取成功,要么自动返回Http404 # 第一个参数表示要获取的数据模型 # 第二个参数是获取条件 question = get_object_or_404(Question, pk=question_id) try: # 获取投票选项 # question.choice_set.get()是数据库API的写法 # request.POST[]以字符串形式返回选择的Choice的ID selected_choice = question.choice_set.get(pk=request.POST['choice']) # 如果在request.POST['choice']数据中没有提供choice,POST将引发一个KeyError except (KeyError, Choice.DoesNotExist): # 如果choice不存在引发KeyError,就返回polls/detail.html页面 # render()用于返回HttpResponse对象 # 第一个参数request是固定且必要的 # 第二个参数是绑定的页面模板 # 第三个参数是传到模板中的参数,是一个字典类型 return render(request, 'polls/detail.html', { 'question': question, 'error_message': "You didn't select a choice.", }) else: # 选票加一 selected_choice.votes += 1 # 保存选票数据 selected_choice.save() # 重定向到polls:results的链接,参数是url # reverse()用于对url反向解析:把名字变为链接 # 第一个参数是url的名字,路由urls.py里面命名的 # 第二个参数是url的参数,是一个元组类型 return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
代码中的一些说明:
(1)代码中的 polls/index.html、polls/detail.html、polls/results.html 等 HTML 文件是页面,页面模板 Templates 将在下一篇介绍,这里先这样写着,留个坑下篇填
(2)数据库API:由Django 提供的用于访问数据库的接口,比如Question.objects.filter() 用于筛选,其写法需要学习,官方文档:https://docs.djangoproject.com/zh-hans/2.1/topics/db/queries/
(3)request.POST['choice']以字符串形式返回选择的 Choice 的 ID。request.POST 的值永远是字符串,如果在 request.POST['choice'] 数据中没有提供 choice,POST 将引发一个 KeyError
(4)render() 是 Views 里面一个常用的重要函数,通过第二个参数来关联页面模板,第三个参数向模板传参,实现了Views 与 Templates 的交互
(5)重定向就是跳转的意思,他的参数是url
(6)reverse() 是反向解析函数:解析是把 url 用它的名字代替,参见 urls,py 里的命名空间和 name;反向解析就是把名字还原成 url,比如对于代码中的 'polls:results' ,根据查找 urls.py 里的路由表,可反向解析为 '<int:pk>/results/' ,再根据参数 args=(question.id,) ,就解析成 'question.id/results/' (其中 question.id 已经是具体数字),这样就完整地实现了从 name 到 url 的反向解析,然后就可以做作为参数传给重定向函数 HttpResponseRedirect( ) 了