本教程上接Django 1.10中文文档-第一个应用Part2-模型和管理站点。我们将继续开发网页投票这个应用,主要讲如何创建一个对用户开放的界面。
概览
视图是Django应用中的一“类”网页,它通常使用一个特定的函数提供服务,并且具有一个特定的模板。例如,在博客应用中,可能有以下视图:
-
博客首页 —— 显示最新发表的博客;
-
博客“详细”页面 —— 每博客的链接页面;
-
基于年份的归档页面 —— 显示特定年内所有月份发表过的博客;
-
基于月份的归档页面 —— 显示特定月份内每天发表过博客;
-
基于日期的归档页面 —— 显示特定日期内发表过的所有博客;
-
评论:处理针对某篇博客发布的评论。
在我们的投票应用中,我们将建立下面的四个视图:
-
Question首页 —— 显示最新发布的几个Question;
-
Question“详细”页面 —— 显示单个Question的具体内容,提供一个投票的表单,但不显示该议题的当前投票结果;
-
Question“结果”页面 —— 显示特定的Question的投票结果;
-
投票功能 —— 处理对Question中Choice的投票。
在Django中,网页的页面和其他内容都是由视图(views.py)来传递的(视图对WEB请求进行回应)。每个视图都是由一个Python函数(或者是基于类的视图的方法)表示。Django通过对比请求的URL地址来选择对应的视图。
在你平时的网页上,你可能经常会碰到类似“ME2/Sites/dirmod.asp?sid=&type=gen&mod=Core+Pages&gid=A6CD4967199A42D9B65B1B”的url。庆幸的是Django支持使用更加简介的URL模式(patterns),而不需要编写上面那种复杂的url。
URL模式就是一种URL的通用模式 —— 例如: /newsarchive/<year>/<month>/
。
Django使用‘URLconfs’的配置来为URL匹配视图函数。 URLconf使用正则表达式将URL匹配到视图上。
本教程提供URLconfs基本使用,更多信息请参考django.url
编辑视图
下面,让我们打开polls/views.py文件,添加下列代码:
# polls/views.py
def detail(request, question_id):
return HttpResponse("You're looking at question %s." % question_id)
def results(request, question_id):
response = "You're looking at the results of question %s."
return HttpResponse(response % question_id)
def vote(request, question_id):
return HttpResponse("You're voting on question %s." % question_id)
然后,在polls/urls.py文件中加入下面的url模式,将其映射到我们上面新增的视图。
# polls/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
# ex: /polls/
url(r'^$', views.index, name='index'),
# ex: /polls/5/
url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'),
# ex: /polls/5/results/
url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'),
# ex: /polls/5/vote/
url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
]
现在去浏览器中访问“/polls/34/”它将运行detail()方法,然后在页面中显示你在url里提供的ID。访问“/polls/34/results/”和“/polls/34/vote/”,将分别显示预定义的伪结果和投票页面。
上面访问的路由过程如下:当有人访问“/polls/34/”地址时,Django将首先加载mysite.urls模块,因为它是settings文件里设置的ROOT_URLCONF配置文件。在模块里找到urlpatterns变量,按顺序对各项进行正则匹配。当它匹配到了^polls/,就剥离出url中匹配的文本polls/,然后将剩下的文本“34/”,传递给“polls.urls”进行下一步的处理。在polls.urls,又匹配到了r’^(?P<question_id>[0-9]+)/$’
,最终结果就是调用该模式对应的detail()视图,将34作为参数传入:
detail(request=<HttpRequest object>, question_id='34')
question_id=’34’的部分来自(?P <question_id> [0-9])
。使用模式周围的括号“捕获”该模式匹配到的文本,并将其作为参数发送到视图函数;?P<question_id>
定义一个名字用于标识匹配的模式;[0-9]+
是匹配一串数字的正则表达。
因为URL模式是正则表达式,你如何使用它们没有什么限制。 不需要添加像.html这样繁琐的URL —— 除非你执意这么做,在这种情况下你可以这样做:
url(r'^polls/latest\.html$', views.index),
但是,不要这样做。这比较愚蠢。
编写拥有实际功能的视图
每个视图函数只负责处理两件事中的一件:返回一个包含所请求页面内容的HttpResponse对象,或抛出一个诸如Http404异常。该如何去做这两件事,就看你自己的想法了。
您的视图可以从数据库读取记录,也可以不读取。它可以使用模板系统:如Django的或第三方Python模板系统 或不。可以生成PDF文件,输出XML,即时创建ZIP文件,任何你想要的,使用任何你想要的Python库。Django只要求返回的是一个HttpResponse。 或者抛出一个异常。
为了方便,让我们使用Part1中介绍的Django自己的数据库API。 下面是一个新的index()视图,它显示系统中最新发布的5条questions记录,并用逗号分隔:
# polls/views.py
from django.http import HttpResponse
from .models import Question
def index(request):
latest_question_list = Question.objects.order_by('-