编写你的第一个 Django 应用,第 4 部分¶这一篇从 教程第 3 部分 结尾的地方继续讲起。我们将继续编写投票应用,专注于简单的表单处理并且精简我们的代码。 编写一个简单的表单¶让我们更新一下在上一个教程中编写的投票详细页面的模板 ("polls/detail.html") ,让它包含一个 HTML polls/templates/polls/detail.html¶ <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> 简要说明:
现在,让我们来创建一个 Django 视图来处理提交的数据。记住,在 教程第 3 部分 中,我们为投票应用创建了一个 URLconf ,包含这一行: polls/urls.py¶ path('<int:question_id>/vote/', views.vote, name='vote'), 我们还创建了一个 polls/views.py¶ from django.http import HttpResponse, HttpResponseRedirect from django.shortcuts import get_object_or_404, render from django.urls import reverse from .models import Choice, Question # ... 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): # Redisplay the question voting form. return render(request, 'polls/detail.html', { 'question': question, 'error_message': "You didn't select a choice.", }) else: selected_choice.votes += 1 selected_choice.save() # Always return an HttpResponseRedirect after successfully dealing # with POST data. This prevents data from being posted twice if a # user hits the Back button. return HttpResponseRedirect(reverse('polls:results', args=(question.id,))) 以上代码中有些内容还未在本教程中提到过:
正如在 教程第 3 部分 中提到的, 当有人对 Question 进行投票后, polls/views.py¶ from django.shortcuts import get_object_or_404, render def results(request, question_id): question = get_object_or_404(Question, pk=question_id) return render(request, 'polls/results.html', {'question': question}) 这和 教程第 3 部分 中的 现在,创建一个 polls/templates/polls/results.html¶ <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> 现在,在你的浏览器中访问 注解 我们的 这个问题被称为 竞争条件 。如果你对此有兴趣,你可以阅读 Avoiding race conditions using F() 来学习如何解决这个问题。 使用通用视图:代码还是少点好¶
这些视图反映基本的 Web 开发中的一个常见情况:根据 URL 中的参数从数据库中获取数据、载入模板文件然后返回渲染后的模板。 由于这种情况特别常见,Django 提供一种快捷方式,叫做“通用视图”系统。 通用视图将常见的模式抽象化,可以使你在编写应用时甚至不需要编写Python代码。 让我们将我们的投票应用转换成使用通用视图系统,这样我们可以删除许多我们的代码。我们仅仅需要做以下几步来完成转换,我们将:
请继续阅读来了解详细信息。 为什么要重构代码? 一般来说,当编写一个 Django 应用时,你应该先评估一下通用视图是否可以解决你的问题,你应该在一开始使用它,而不是进行到一半时重构代码。本教程目前为止是有意将重点放在以“艰难的方式”编写视图,这是为将重点放在核心概念上。 就像在使用计算器之前你需要掌握基础数学一样。 改良 URLconf¶首先,打开 polls/urls.py¶ from django.urls import path from . import views app_name = 'polls' urlpatterns = [ 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'), ] 注意,第二个和第三个匹配准则中,路径字符串中匹配模式的名称已经由 改良视图¶下一步,我们将删除旧的 polls/views.py¶ from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404, render from django.urls import reverse from django.views import generic from .models import Choice, Question class IndexView(generic.ListView): template_name = 'polls/index.html' context_object_name = 'latest_question_list' def get_queryset(self): """Return the last five published questions.""" 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): ... # same as above, no changes needed. 我们在这里使用两个通用视图:
默认情况下,通用视图 类似地, 在之前的教程中,提供模板文件时都带有一个包含 启动服务器,使用一下基于通用视图的新投票应用。 |
|
来自: 宁静致远oj1kn5 > 《官网》