看了刘江老师教程这么多天,卧槽,我才发现他也曾跻身于行伍之间,interesting

刘老师这波讲解很到位,告诉你如何编写单例视图的时候忽然告诉你,其实不用这么麻烦,我们有通用视图,那些总是要做相似的行为的视图,咱们就写一个好了,解放生产力不就是进步吗?

好的废话不说进入正题,先修改一波detail.html模板

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>detail</title>
</head>
<body>
<h1>{{ question.question_text }}</h1>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
{% for choice in question.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">
<label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
{% endfor %}
<input type="submit" value="Vote">
</form>
</body>
</html>

解读一些这个html,

h1是一级标题,里面用了传入的question对象的question_text属性,在本实例之中得到的就是问题的名字

接下来用了判断,这里看就是关于报错信息的,如果有,则会出现一句加粗的提示,内容就是。。。报错信息

接下来是一个文本框,radio类型是单选按钮,label里面for属性表示的是关联哪个表单,这里我们看到input文本框的id和for的值是相同的,也就是为label和此处的input做了绑定,于是你就get到了此处显示的信息为:

问题名

选项1

选项2

按钮VOTE

回顾一下我们已有的有灵魂和躯体的家伙们(有views中定义且有对应路由渲染模板)index、detail、results

那么这个vote呢?vote这里它就是个灵魂,就是个贾维斯,我们不需要它有一个躯壳它就可以完成使命!也就是说它做逻辑业务

现在对views.py中的vote功能进行改写

def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected_choice = question.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
return render(request, 'polls/detail.html', {
'question': question,
'error_message': "You didn't select a choice.",
})
else:
selected_choice.votes += 1
selected_choice.save()
return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

那么results就需要模板,在polls/templates/polls/下创建新的html文件results.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>{{ question.question_text }}</h1> <ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul> <a href="{% url 'polls:detail' question.id %}">Vote again?</a>
</body>
</html>

注意这里返回的对象不再是HttpResponse对象而是进行了重定向,跳转到结果页面

当我们在detail提交表单就会跳转执行vote函数,紧接着vote通过判断被传入的id对数据库进行操作即votes属性(字段)+1,保存,跳转结果

为了解决冗余,引入通用视图

修改views.py

from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse, Http404, HttpResponseRedirect
from django.template import loader
from django.urls import reverse
from django.views import generic from .models import Question, Choice # def index(request):
# return HttpResponse("hello world,you are at the polls index!")
class IndexView(generic.ListView):
template_name = 'polls/index.html'
context_object_name = 'latest_question_list' def get_queryset(self):
"""Return the last five published question."""
return Question.objects.order_by('-pub_date')[:5] class DetailView(generic.DetailView):
model = Question
template_name = 'polls/detail.html' class ResultsView(generic.DetailView):
model = Question
template_name = 'polls/results.html' def vote(request,question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected_choice = question.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
return render(request, 'polls/detail.html', {
'question': question,
'error_message': "You didn't select a choice.",
})
else:
selected_choice.votes += 1
selected_choice.save()
return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
# Create your views here.

generic.ListView(显示一个对象列表)和DetailView(显示详细内容)是django两个通用视图类,这里在创建我们自己的视图的时候继承了这两个父类

由于DetailView需要从url中获取名为pk的主键值,所以在urls中修改了question_id为pk。

DetailView视图默认使用一个叫做<app name>/<model name>_detail.html的模板,而此处我们选哟用自己的模板,template_name这个属性就是告诉django我们的默认模板是什么,通过具体指定。

对于ListView视图来说默认模板我们用自己的和Detail雷同的方式,但是对于Listview视图来说默认传递信息的上下文变量是question_list,这里由于我们的页面index中设置的上下文变量叫做

latest_question_list,所以我们需要通过设置context_object_name属性来覆盖。

当你更改了views后,这时候需要对urls也重新配置

polls/urls.py

from django.urls import path
from . import views app_name = 'polls'
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
# ex:/polls/5
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
# ex:/polls/5/results
path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
# ex:/polls/5/vote/
path('<int:question_id>/vote/', views.vote, name='vote'),
]

然后你就可以在你的投票界面愉快的玩耍了

试着点选项和Vote试试?


题外话,当你创建了app之后,你的8000端口进入页面就一直都是404,这是因为有了app之后服务器从localhost:8000后面开始寻找pysite/urls.py中的配置,它无法找到""这个对应的模板,解决的办法就是手动给pysite添加views和templates并在urls.py中设置""对应的视图和名字,然后比如我这个就是这样:

最新文章

  1. mac 下载安装 IntelliJ IDEA Tomcat
  2. ural 2070. Interesting Numbers
  3. SQL语句调优 - 统计信息的含义与作用及维护计算
  4. Jquery 弹出提示框输入插件 apprise 修改中文按钮以及使用说明
  5. Oracle11g TNS-12541:TNS无监听程序
  6. grunt 合并压缩任务
  7. 黑马程序员——利用swap函数研究C的指针
  8. Google搜索的配置方法
  9. 用tomcat搭建web服务器
  10. JavaScript 闭包总结 (深入理解)
  11. JavaSE教程-02Java基本语法-练习
  12. js_3_for_if_try
  13. NIO基础篇(二)
  14. unity 面试题(答案)
  15. thinkphp5省市区三级联动例子
  16. Java编程的逻辑 (87) - 类加载机制
  17. [LeetCode] 100. Same Tree_Easy tag: DFS
  18. 通过junit/TestNG+java 实现自动化测试
  19. (转载)Ubuntu下安装Qt
  20. java new关键字

热门文章

  1. Spring Boot 如何部署到 Linux 中的服务
  2. mysql 运行中 偶尔 报错 2002 也许是这个问题,内存不足导致的
  3. spring boot + swagger2
  4. 学完微型服务器(Tomcat)对其工作流程的理解,自己着手写个简单的tomcat
  5. html5获取地理位置和定位
  6. Raspberry Pi 4B 使用OpenCV访问摄像头picamera模块
  7. include指令与jsp:include动作标识的区别
  8. elasticsearch _source
  9. Maven:禁止编码指定类型的资源文件
  10. 免费版CloudFlare CDN基本设置参考