一、问题详情页
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>展示某个投票的问题和不带结果的选项列表</title>
</head>
<body>
<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
<fieldset>
<legend><h1>{{ question.question_text }}</h1></legend>
{% if error_message %}<p><strong> {{ error_message }}</strong> </p> {% endif %}
{% 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>
<li>{{ choice.choice_text }}</li>
{% endfor %}
</fieldset>
<input type="submit" value="Vote">
</form>
</body>
</html>
二、问题结果页
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_test }} -- {{ choice.votes }}</li>
{% endfor %}
</ul>
{# 跳转到某一问题的投票详情页#}
<a href="{% url 'polls:detail' question.id %}">vote again?</a>
</body>
</html>
三、投票处理器视图
python
# 3.投票处理器:用于响应用户为某个问题的特定选项投票的操作
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",
{
"quesiton":question,
"error_message":"You didn't select a choice"
}
)
else:
selected_choice.votes = F("votes") + 1
selected_choice.save()
return HttpResponseRedirect(reverse("polls:results",args=(question.id,)))
四、引入通用视图之前的urlCONF
python
from django.urls import path
from . import views
# 为视图函数配置url
# name
# 设置app的命名空间,主要是为了区分不同app下相同名字的视图
app_name = "polls"
urlpatterns = [
# 当 Django 响应一个请求时,它会从 urlpatterns 的第一项开始,按顺序依次匹配列表中的项,直到找到匹配的项。
# 比如URLconf 在处理请求 https://www.example.com/myapp/ 时,它会尝试匹配 myapp/
path("",views.index,name= "index"),
path("<int:question_id>/",views.detail,name = "detail"),
path("<int:question_id>/results/", views.results, name = "results"),
path("<int:question_id>/vote/", views.vote, name = "vote"),
]
五、引入通用视图
python
from django.db.models import F
from django.http import HttpResponse, Http404,HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.urls import reverse
from django.views.generic import ListView
from django.views import generic
# Create your views here.
from .models import Question,Choice
class indexView(generic.ListView):
# 默认情况下,ListView使用一个叫做 <app name>/<model name>_list.html的默认模板
# 因此默认模板为polls/index_list.html
# 此例我本手动指定template_name为"polls/index.html"
template_name = "polls/index.html"
# 默认的上下文变量名(其对应的值会传递到index.html)为question_list(命名规则:模板名小写_list)
# 因为之前的代码中,在index.html中引用的变量名都是latest_question_list,因此使用context_object_name覆盖默认的行为
context_object_name = "latest_question_list"
# 如果不重写get_queryset,而使用默认的 model = Question
# 其实等价于 Question.objects.all()
def get_queryset(self):
"""返回最近5个发布的问题"""
return Question.objects.order_by("-pub_date")[:5]
# latest_question_list = Question.objects.order_by("-pub_date")[:5]
# context = {"latest_question_list":latest_question_list}
# return render(request,"polls/index.html",context)
# output = ", ".join([q.question_text for q in latest_question_list])
# return HttpResponse(output)
# 1.问题详情页:展示某个投票的问题和不带结果的选项列表
class detailView(generic.DetailView):
model = Question
template_name = "polls/detail.html"
# 404异常处理-传统方式
# try:
# question = Question.objects.get(pk=question_id)
# except Question.DoesNotExist:
# raise Http404("Quesition does not exit")
# 404异常处理-利用Django提供的函数
# question = get_object_or_404(Question,pk=question_id)
# return render(request,"polls/detail.html",{"question":question})
# 2.问题结果页:展示某个投票的结果
class resultsView(generic.DetailView):
model = Question
template_name = "polls/result.html"
# question = get_object_or_404(Question,pk= question_id)
# return render(request,"polls/result.html",{"question":question})
# 3.投票处理器:用于响应用户为某个问题的特定选项投票的操作
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",
{
"quesiton":question,
"error_message":"You didn't select a choice"
}
)
else:
selected_choice.votes = F("votes") + 1
selected_choice.save()
return HttpResponseRedirect(reverse("polls:results",args=(question.id,)))
六、引入通用视图之后的urlCONF
第二和第三个模式的路径字符串中匹配的模式名称已从 <question_id>
更改为 <pk>
。这是因为我们将使用 DetailView 通用视图来替换我们的 detail()
和 results()
视图,它期望从 URL 中捕获的主键值被称为 "pk"
。
python
from django.urls import path
from . import views
# 为视图函数配置url
# name
# 设置app的命名空间,主要是为了区分不同app下相同名字的视图
app_name = "polls"
urlpatterns = [
# 当 Django 响应一个请求时,它会从 urlpatterns 的第一项开始,按顺序依次匹配列表中的项,直到找到匹配的项。
# 比如URLconf 在处理请求 https://www.example.com/myapp/ 时,它会尝试匹配 myapp/
path("",views.indexView.as_view(),name= "index"),
path("<int:pk>/",views.detailView.as_view(),name = "detail"),
path("<int:pk>/results/", views.resultsView.as_view(), name = "results"),
path("<int:question_id>/vote/", views.vote, name = "vote"),
]