English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
在上一节的教程中,我们介绍了 Django的视图,并编写了一个简单的实例。本小节我们将学习网络投票应用程序,并将侧重于简单的表单处理,以最少代码代码量来实现。
让我们更新 poll detail 模板(“polls/detail.html) ,从上个教程,在模板 polls/templates/polls/detail.html 包含一个HTML<form>元素:
# Filename : example.py # Copyright : 2020 By w3codebox # Author by : ko.oldtoolbag.com # Date : 2020-08-08 <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>/label><br /> {% endfor %} <input type="submit" value="Vote" /> </form>이 템플릿은 각 질문 선택을 단일 선택 버튼으로 표시합니다. 각 단일 선택 버튼의 값은 질문 선택 번호와 연결됩니다. 각 단일 선택 버튼의 이름은 "choice"입니다. 이는 누군가가 단일 선택 버튼을 선택하고 양식을 제출하면 POST 데이터 choice=#이 전송된다는 것을 의미합니다. 이는 HTML 양식의 기본 개념입니다. 우리는 양식의 액션 {% url 'polls:vote' question.id %}을 설정하고 method="post"을 설정합니다. method="post"(method="get"에 비해)을 사용하는 것은 매우 중요합니다. 이 양식을 제출하면 서버 측 데이터가 변경됩니다. 데이터를 변경하는 서버 측 양식을 생성할 때 method="post"을 사용합니다. 이 문서는 Django에 대해서만 적은 것이 아닙니다; 이는 좋은 웹 개발 관행입니다. forloop.counter는 양식 태그가 몇 번의 루프를 통과했는지를 나타냅니다 우리가 POST 형식을 생성하고 있기 때문에(데이터를 수정할 수 있음), 콘솔루트 요청 조작에 대한 걱정이 필요합니다. 그러나 걱정하지 마세요, Django는 매우 쉽게 사용할 수 있는 보호 시스템을 제공합니다. 요약하면, 모든 내부 URL에 대해 POST 형식은 {% csrf_token %} 템플릿 태그를 사용해야 합니다.
우리는 vote() 함수의 가상 구현을 생성했습니다. 실제 버전을 생성해야 합니다. 다음 코드를 polls 파일에 추가하세요/views.py:
polls/views.py 파일의 내용은 다음과 같습니다:
# Filename : example.py # Copyright : 2020 By w3codebox # Author by : ko.oldtoolbag.com # Date : 2020-08-08 from django.shortcuts import get_object_or_404, render from django.http import HttpResponseRedirect, HttpResponse from django.core.urlresolvers 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): # 질문 투표 양식을 다시 표시합니다. return render(request, 'polls/detail.html', { 'question': question, 'error_message': "You didn't select a choice.", ) else: selected_choice.votes += 1 selected_choice.save() # 데이터를 성공적으로 처리한 후 항상 HttpResponseRedirect를 반환합니다. # POST 데이터와 함께. 이는 데이터가 두 번 이상 게시되지 않도록 방지합니다. # 사용자가 Back 버튼을 누릅니다. return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
이 코드는 여기서 다루지 않은 몇 가지 것들이 포함되어 있습니다:
request.POST는 딕셔너리와 유사한 객체이며, 키 이름을 통해 제출된 데이터에 접근할 수 있습니다. 이 경우, request.POST['choice']는 선택된 choice의 ID를 문자열로 반환합니다. request.POST의 값은 항상 문자열입니다.
주의: Django는 request.GET를 통해 동일한 방식으로 GET 데이터에 접근도 제공합니다 – 하지만 우리의 코드에서는 request.POST을 명확히 사용하여 데이터가 POST 호출을 통해만 수정될 수 있도록 합니다.
POST 데이터에 choice가 제공되지 않으면, request.POST['choice']는 KeyError 예외를 발생시킵니다. 위의 코드는 choice가 제공되지 않았을 때 KeyError 예외와 오류 메시지를 표시하는 양식을 확인합니다.
선택 choice 계산이 증가된 후, 코드는 HttpResponse Redirect를 반환하는 대신 일반적인 HttpResponse를 반환합니다. HttpResponseRedirect는 파라미터가 필요합니다: 사용자가 이동할 URL(다음을 참조하십시오)-我们如何构建在这种情况下的URL)。
如上Python的注释所指出的,应该总是在 POST 数据处理成功 后返回一个HttpResponse重定向。
在本示例中我们使用的是 HttpResponseRedirect 构造reverse()函数。此函数有助于避免硬编码URL在视图中。这是因为我们想通过控制并指向该视图的URL模式的可变部分的视图的名称。在这种情况下,使用 URLconf 配置使 reverse()调用返回字符串如:
# Filename : example.py # Copyright : 2020 By w3codebox # Author by : ko.oldtoolbag.com # Date : 2020-08-08 '/polls/3/results/'
其中3是question.id的值。然后,这个重定向的URL将调用“results”视图中显示的最后一页。
现在访问网址:http://127.0.0.1:8000/polls/1/ 得到结果如下所示: 当有人在一个问题投票后,vote() 视图重定向到该问题的结果页面。让我们编写这个视图(polls/views.py):
# Filename : example.py # Copyright : 2020 By w3codebox # Author by : ko.oldtoolbag.com # Date : 2020-08-08 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})
现在,创建一个 polls/results.html (polls/templates/polls/results.html)模板:
# Filename : example.py # Copyright : 2020 By w3codebox # Author by : ko.oldtoolbag.com # Date : 2020-08-08 <h2>{{ question.question_text }}</h2> <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 %}">다시 투표?</a>
이제, 브라우저에서 열어주세요 /polls/1/ 투표에 대한 질문이 있어야 합니다. 투표를 할 때마다 업데이트된 결과 페이지가 표시되어야 합니다. 폼을 제출했을 때 옵션을 선택하지 않으면 오류 메시지가 표시되어야 합니다. 옵션을 선택하고 제출하면 다음과 같은 결과가 표시되어야 합니다:
먼저, polls/urls.py를 수정하십시오:
from django.conf.urls import url from . import views app_name = 'polls' urlpatterns = [ url(r'^$', views.IndexView.as_view(), name='index'), url(r'^(?P<pk>[0-9]+)/$, views.DetailView.as_view(), name='detail'), url(r'^(?P<pk>[0-9]+)/results/$, views.ResultsView.as_view(), name='results'), url(r'^(?P<question_id>[0-9]+)/vote/$, views.vote, name='vote'), ]