![Django 3.0入门与实践](https://wfqqreader-1252317822.image.myqcloud.com/cover/246/36862246/b_36862246.jpg)
3.10 添加视图
现在网站的后台管理模块已经可以工作了,还缺少前台页面。投票系统需要以下几个页面:
问题索引页——展示最近的几个投票问题。
问题详情页——展示某个投票的问题和不带结果的选项列表。
问题结果页——展示某个投票的结果。
投票处理器——用于响应用户为某个问题的特定选项投票的操作。
在Django中每一个页面或者其他内容都是通过视图呈现出来的,每一个视图就是一个Python函数或者类方法,Django中的视图是“一类具有相同功能和模板的网页的集合”。Django通过URL确定调用哪一个视图,Django的URL相较于早期网站的URL更加简洁优雅。
Django通过URLconfs将URL模式字符串与视图关联起来,URL模式字符串就是一个URL的一般形式,如/newsarchive/<year>/<month>/。
在polls/views.py文件中添加以下视图:
![](https://epubservercos.yuewen.com/B89DD0/19549641008916106/epubprivate/OEBPS/Images/Figure-P30_149232.jpg?sign=1739604987-5o4h9RTSwJLVlvwsOdhd6vJoTL1NZSls-0-9e4ac3d954dad0d581095c08b86ab299)
修改polls.urls文件,添加以下URL映射:
![](https://epubservercos.yuewen.com/B89DD0/19549641008916106/epubprivate/OEBPS/Images/Figure-P30_149234.jpg?sign=1739604987-Hezix49EBy8A8rdOttXjgPydPDrYrFnz-0-2c48dde062e9be0e8b6184cc0bf3b3c6)
好了,重启Web服务器,在浏览器中访问http://127.0.0.1:8000/polls/24/,如下图所示。
![](https://epubservercos.yuewen.com/B89DD0/19549641008916106/epubprivate/OEBPS/Images/Figure-P30_15499.jpg?sign=1739604987-cG883TndcrQY3vXoivwFf7pf667T7TtJ-0-919a4ae7011f8572ba9420b260f9c584)
继续访问http://127.0.0.1:8000/polls/24/results/和http://127.0.0.1:8000/polls/24/vote/,同样能够正常显示视图内容,如下面两幅图所示。
![](https://epubservercos.yuewen.com/B89DD0/19549641008916106/epubprivate/OEBPS/Images/Figure-P31_15937.jpg?sign=1739604987-gfqcSgL2HbPyWnN7pHo7u1rb9jc6Uyv3-0-d15f5534a6c3894b6597ae404291e1ad)
![](https://epubservercos.yuewen.com/B89DD0/19549641008916106/epubprivate/OEBPS/Images/Figure-P31_15938.jpg?sign=1739604987-GxrCSpQZzdRPxODHdMKUkDE4ywgj3BoK-0-d70d95cc3a13586998241858153f64fd)
之所以Django能够正常调用解析URL,是因为在settings.py中设置了ROOT_URLCONF = 'mysite.urls'。当用户访问的URL包含polls/时,Django会根据mysite.urls中的设置,跳转到polls.urls并进行验证,直到找到第一个匹配的URL为止。
以上视图中参数question_id的值来自于<int:question_id>。<int:question_id>用于匹配URL中的值,并将捕捉到的值作为关键字参数传递给视图,其中:question_id对应视图的参数,int:决定了URL中的哪类值符合匹配条件。
3.10.1 扩展视图
每一个视图都应该负责一个具体的业务逻辑,视图执行结束会返回一个包含页面内容的HttpResponse对象或者异常信息。
下面修改index视图使它返回最新的5条调查问卷。
![](https://epubservercos.yuewen.com/B89DD0/19549641008916106/epubprivate/OEBPS/Images/Figure-P31_149236.jpg?sign=1739604987-Jqt6cjcQIQBaOXuaqXOyHVL02F4u9Amy-0-95f617bce18a217da5d8f1c0a49f50f5)
代码Question.objects.order_by('-pub_date')是Django的数据库API语法,用于从数据库中查找数据,在介绍模型时将进行详细讲解。
访问index页面以查看显示情况,如下图所示。
![](https://epubservercos.yuewen.com/B89DD0/19549641008916106/epubprivate/OEBPS/Images/Figure-P32_16405.jpg?sign=1739604987-XGKcC7aY8ycjn2bFmi0ljVRhnkknvwPl-0-e08fea2c304101ea91f791f24cd0d943)
此时调查问卷已经显示到网页上,但是可以发现在index视图中使用了硬编码,如果想要修改网页显示样式就需要重新编写Python代码。对此Django提供了一套模板系统(templates),可以将业务逻辑与页面显示样式分离开。下面来看看如何使用模板系统。
首先在polls文件夹下创建一个新文件夹templates,为了目录结构清晰,在templates文件夹下再创建一个polls文件夹,最后在polls下创建一个index.html文件。这个index.html就是即将应用于index视图的模板。
在settings.py中有一个关于模板的配置项:TEMPLATES。Django就是根据这个配置查找并解析模板的,具体工作原理会在第5章进行讲解。
将下面代码写入模板文件index.html:
![](https://epubservercos.yuewen.com/B89DD0/19549641008916106/epubprivate/OEBPS/Images/Figure-P32_149238.jpg?sign=1739604987-er5ixzqQPpOobdBPgPJ4Vc7EkGpLceKx-0-1118efa8763e504390e683ad64aed5a4)
接下来修改index视图:
![](https://epubservercos.yuewen.com/B89DD0/19549641008916106/epubprivate/OEBPS/Images/Figure-P32_149240.jpg?sign=1739604987-KuxbDpX8ZeH4xQhhnbh2MmhYjSaHvYt7-0-a71f309c0b1eeb3d6f859ce3c8033273)
新视图会从模板文件夹下加载模板文件并将一个字典对象传入视图。
重启Web服务器,刷新index页面,效果如下图所示。
![](https://epubservercos.yuewen.com/B89DD0/19549641008916106/epubprivate/OEBPS/Images/Figure-P33_16866.jpg?sign=1739604987-RgIh0q9nnfh1WRcEIIwXbKiLnYFZ1sFI-0-40a170db66bac3b39f6f61bcee89f382)
上面代码的工作原理是先使用loader方法加载模板文件并向它传递一个上下文对象(context),然后使用HttpResponse方法初始化一个HttpResponse对象并返回给浏览器。由于很多Django视图都是这样工作的,因此Django提供了一个简写函数:render()。下面使用render函数重写index视图:
![](https://epubservercos.yuewen.com/B89DD0/19549641008916106/epubprivate/OEBPS/Images/Figure-P33_149247.jpg?sign=1739604987-rjLBjq5K11SZj8dCNldopvccKLbgSXvB-0-6065cbcf506c4aa9815b2bfdbf99dbb4)
此时重新访问index页面时可以发现效果与之前一样,但是不再需要loader和HttpResponse方法。
3.10.2 处理404错误
404错误是一个比较常见的网页访问错误,当被访问的URL资源不存在时就会抛出这类错误。下面修改detail视图使其在无法查找到问卷的时候抛出404错误。
![](https://epubservercos.yuewen.com/B89DD0/19549641008916106/epubprivate/OEBPS/Images/Figure-P33_149245.jpg?sign=1739604987-ETuLSZVYi0g7aKZDgoZS3m6JDwGofpUa-0-1450dc0ad5fbbb92bf3e592f1acd33d7)
按照前面步骤在polls文件夹下创建一个detail.html文件作为detail视图的模板文件,模板内容暂时用{{ question }}表示。
此时重启Web服务,分别访问一个存在的和一个不存在的问卷,效果如下面两幅图所示。
![](https://epubservercos.yuewen.com/B89DD0/19549641008916106/epubprivate/OEBPS/Images/Figure-P33_16872.jpg?sign=1739604987-QzhZlo5Tyyt25fILGhM7SmSMlQcyWTnF-0-19fa96cd409da0e9296ee65213cf989d)
![](https://epubservercos.yuewen.com/B89DD0/19549641008916106/epubprivate/OEBPS/Images/Figure-P34_17312.jpg?sign=1739604987-7ngNDc5NwdmWoL9ImAsfFCIOVSFFlsVz-0-607b6f0fe36fcdaba814dc35d9cac141)
由于404错误是一个非常常见的网页异常,因此Django也提供了一个简写方法:get_object_or_404。下面使用get_object_or_404()修改detail视图:
![](https://epubservercos.yuewen.com/B89DD0/19549641008916106/epubprivate/OEBPS/Images/Figure-P34_149249.jpg?sign=1739604987-d3lA3wwSviB5ml4CDBQTXaY6XzFN3yjw-0-8e00318979531557cb0a474aeea50cfd)
重新访问detail页面,效果如下图所示。
![](https://epubservercos.yuewen.com/B89DD0/19549641008916106/epubprivate/OEBPS/Images/Figure-P34_17316.jpg?sign=1739604987-9u5mwWhn7UJr1P8t2tICOROCevsn4NyV-0-330026b1116751a11e6867893f9921dc)
此时网页仍然抛出404错误,不过错误信息变成Django默认的英文形式,此时可以通过修改get_object_or_404()方法源代码的方式修改错误信息,修改完需要重启Web服务。
与get_object_or_404相似,Django还提供了一个判断list是否存在的方法:get_list_or_404,在此不做详细介绍。