English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Django快速入门-表单

在上一节的教程中,我们介绍了 Django的视图,并编写了一个简单的实例。本小节我们将学习网络投票应用程序,并将侧重于简单的表单处理,以最少代码代码量来实现。

编写一个简单的表单

让我们更新 poll detail 模板(“polls/detail.html) ,从上个教程,在模板 polls/templates/polls/detail.html 包含一个HTML<form>元素:

# Dateiname : example.py
# Urheberrecht : 2020 Von w3codebox
# Autor von : de.oldtoolbag.com
# Datum : 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=#,其中#是被选择的选择的ID。这是HTML表单的基本概念。  
  我们设置表单的动作 {% url 'polls:vote' question.id %},以及设置 method="post". 使用 method="post" (相对于 method="get") 非常重要,因为提交此表单将改变服务器端数据的行为。当创建一个会改变服务器端数据的表单时,使用 method="post". 这篇文章不仅仅针对 Django; 这也是一个很好的 Web 开发实践。  
  forloop.counter表示表单标签通过了多少次循环  
  因为我们正在创建一个POST形式(可能会修改数据),我们需要担心跨站请求伪造。但是也不必担心,因为Django自带了一个非常容易使用的保护系统来对抗。总之,这是针对所有内部URL的POST形式都应该使用{%csrf_token%}模板标签。

我们还创建了一个虚拟实现 vote() 函数。现在创建一个实用的版本。将以下代码添加到文件 polls/views.py:

polls/views.py 文件的内容如下:

# Dateiname : example.py
# Urheberrecht : 2020 Von w3codebox
# Autor von : de.oldtoolbag.com
# Datum : 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):
     frage = get_object_or_404(Frage, pk=frage_id)
     try:
         selected_choice = question.choice_set.get(pk=request.POST['choice'])
     except (KeyError, Choice.DoesNotExist):
         # Wiederverwenden des Frageabfrage-Formulars
         return render(request, 'polls/detail.html', {
             'question': question,
             'error_message': "Sie haben keine choice ausgewählt.",
         )
     else:
         selected_choice.votes += 1
         selected_choice.save()
         # Erfolgreiches Verarbeiten
         # mit POST-Daten. Dies verhindert, dass Daten zweimal hochgeladen werden, falls eine
         # Benutzer klickt auf den Zurück-Button
         return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

Dieses Codebeispiel enthält einige Dinge, die noch nicht in diesem Tutorial behandelt wurden:

request.POST ist ein Objekt, das ähnlich einem Dictionary ist und Ihnen ermöglicht, auf die übermittelten Daten über den Schlüsselnamen zuzugreifen. In diesem Fall gibt request.POST['choice'] die ID der ausgewählten choice als String zurück. Der Wert von request.POST ist immer ein String 

Hinweis: Django bietet ebenfalls request.GET an, um GET-Daten auf gleiche Weise abzurufen – aber wir verwenden in unserem Code ausdrücklich request.POST, um sicherzustellen, dass die Daten nur durch POST-Aufrufe geändert werden können

Falls keine choice-Daten bereitgestellt werden, löst request.POST['choice'] eine KeyError-Ausnahme aus. Das obige Codebeispiel überprüft die KeyError-Ausnahme und zeigt eine Fehlermeldung an, falls keine choice angegeben wurde

Nachdem die choice-Zählung erhöht wurde, gibt der Code eine HttpResponse mit Weiterleitung zurück, anstatt eine normale HttpResponse. HttpResponseRedirect benötigt einen Parameter: Der Benutzer wird auf die URL weitergeleitet (siehe unten-Wie bauen wir in diesem Fall die URL auf)。

Wie im Python-Kommentar erwähnt, sollte immer nach dem Erfolg der Verarbeitung von POST-Daten eine HttpResponse-Umleitung zurückgegeben werden.

In diesem Beispiel verwenden wir den HttpResponseRedirect -Konstruktor und die reverse() -Funktion. Diese Funktion hilft, die URL in der Ansicht nicht zu verfestigen, da wir durch die Kontrolle und das Anweisen auf den URL-Modus der Ansicht den Namensbestandteil der URL anpassen möchten. In diesem Fall gibt die reverse() -Aufruf eine Zeichenkette wie folgt zurück:

# Dateiname : example.py
# Urheberrecht : 2020 Von w3codebox
# Autor von : de.oldtoolbag.com
# Datum : 2020-08-08
'/polls/3/results/'

dabei3ist der Wert von question.id. Dann ruft diese Umleitung die letzte Seite der im "results" Ansicht angezeigten URL auf.

Besuchen Sie die folgende Adresse: http://127.0.0.1:8000/polls/1/ Erhalten wir die Ergebnisse wie folgt:   Wenn jemand für eine Frage abstimmt, leitet die vote() Ansicht um zur Ergebnisseite der Frage. Lassen Sie uns diesen Ansicht (polls/views.py):

# Dateiname : example.py
# Urheberrecht : 2020 Von w3codebox
# Autor von : de.oldtoolbag.com
# Datum : 2020-08-08
from django.shortcuts import get_object_or_404, render
 def ergebnisse(request, frage_id):
     frage = get_object_or_404(Frage, pk=frage_id)
     return render(request, 'polls/Ergebnisse.html', {'frage': frage})

Erstellen Sie nun eine polls/Ergebnisse.html (Umfragen/templates/polls/Ergebnisse.html)Template:

# Dateiname : example.py
# Urheberrecht : 2020 Von w3codebox
# Autor von : de.oldtoolbag.com
# Datum : 2020-08-08
<h2>{{ question.question_text }}</h2>
 <ul>
 {% for choice in question.choice_set.all %}
     <li>{{ choice.choice_text }} -- {{ choice.votes }} Stimme{{ choice.votes|pluralize }}</li>
 {% endfor %}
 </ul>
 <a href="{% url 'polls:detail' question.id %}">Vote again?</a>

现在,在浏览器中打开 /polls/1/ 并表决的问题。应该会被每次投票时看到更新结果页。如果您提交表单不选择一个选项,应该看到错误消息。 选择选项,提交后显示如下结果:  

使用通用视图:更少的代码更好

修改URL配置

首先,打开 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'),
]