Dieser Artikel ist eine Reihe, die das offizielle Django-Tutorial weiterentwickelt. Dieses Mal fahren wir mit dem 4. Artikel "Erstellen Ihrer ersten Django-App, Teil 4" fort.
Zusammenfassung des Django-Tutorials für Anfänger von Anfängern ① (Projekterstellung ~) Django-Tutorial-Zusammenfassung für Anfänger von Anfängern Model (Model, Admin) Zusammenfassung des Django-Tutorials für Anfänger von Anfängern ③ (Anzeigen) Zusammenfassung des Django-Tutorials für Anfänger von Anfängern ④ (generische Ansicht) Django Tutorial Zusammenfassung für Anfänger von Anfängern ⑤ (Test) Django Tutorial Zusammenfassung für Anfänger von Anfängern ⑥ (statische Datei) Zusammenfassung der Django-Tutorials für Anfänger durch Anfänger ⑦ (Admin anpassen)
https://docs.djangoproject.com/ja/3.0/intro/tutorial04/
Write a minimal form Platzieren Sie das Abstimmungsformular in der im vorherigen Artikel erstellten Datei "detail.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>
forloop.counter
ist ein Wert, der angibt, wie oft die Schleife des for-Tags ausgeführt wurde.
Wenn Sie sich den Inhalt ansehen, sehen Sie, dass alle Auswahlmöglichkeiten im Zusammenhang mit Frage als Optionsfeldoptionen in der for-Anweisung angezeigt werden.
Sie müssen "{% csrf_token%}" einfügen, wenn Sie ein POST-Formular für CSRF-Maßnahmen erstellen.
Bearbeiten Sie dann polls / views.py
, damit die Abstimmung gut funktioniert.
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,)))
Bei request.POST ['choice']
wird der Wert, der im obigen Formular unter dem Namen'choice 'veröffentlicht wurde, als selected_choice
gelesen.
Ein KeyError wird ausgelöst, wenn request.POST ['choice']
nicht existiert (dh wenn der Benutzer nichts auswählt).
In diesem Fall wird das Formular erneut mit einer Fehlermeldung gerendert.
Wenn der Prozess normal endet, wird er zu den Ergebnissen umgeleitet. (Die Umleitung sollte angewendet werden, wenn die Verarbeitung wie POST normal abgeschlossen ist (unabhängig von Django).)
Sie können das Hardcoating von URLs mit der Funktion "Umkehren" verhindern.
Die Verwendung ähnelt der in index.html
verwendeten URL-Spezifikation.
Fügen Sie nun die Ansicht der Ergebnisse zu polls / views.py
hinzu.
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})
Der Inhalt entspricht fast der Ansicht von "Detail".
Lassen Sie uns auch eine Vorlage erstellen.
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>
Haben Sie bemerkt, dass es bisher ein Problem gibt?
Holen Sie sich im aktuellen Verarbeitungsablauf zuerst "selected_choice" aus der Datenbank, berechnen Sie einen neuen Wert aus den Stimmen und speichern Sie ihn in der Datenbank.
Selbst wenn der Wert der Stimmen ursprünglich 42 war, wenn Herr A und Herr B gleichzeitig abstimmen, wird der Ort, der ursprünglich 44 sein sollte, 43.
Es scheint, dass ein solches Problem als "Konfliktproblem" bezeichnet wird, und der folgende Artikel wird zur Erklärung von "F ()" zur Lösung hilfreich sein. Alle Datensätze, bis Onkel Java Python (Nr. 16) verwenden konnte
Django hat eine Verknüpfung namens Allgemeine Ansicht (allgemeine Ansicht)
Ruft Daten aus der Datenbank gemäß den über die URL übergebenen Parametern ab, lädt die Vorlage und gibt die gerenderte Vorlage zurück. Dies ist so häufig, dass Django eine Verknüpfung anbietet, die als generische Ansicht bezeichnet wird. Eine generische Ansicht ist eine Abstraktion gängiger Muster, mit der Sie eine Anwendung schreiben können, ohne Python-Code zu schreiben.
... anscheinend ...
Ändern Sie polls / urls.py
wie folgt
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'),
]
Der Unterschied besteht darin, dass views.IndexView.as_view ()
usw. an die durch path angegebene Ansicht übergeben wird.
Außerdem wurde "question_id" in "pk" umbenannt. (Der Grund wird später beschrieben)
Erstellen Sie die IndexView
Klasse usw. in der Ansicht.
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.
Es werden "ListView" und "DetailView" verwendet.
Die question_id
wurde in pk
umbenannt, da sie in der DetailView
als solche angegeben ist.
Standardmäßig verwendet die generische Ansicht "DetailView" eine Vorlage mit dem Namen
Recommended Posts