/ / Comment implémenter l'exemple des sondages officiels django de manière équivalente en utilisant des formulaires ? - django, django-forms, modelform

Comment implémenter de manière équivalente l'exemple des sondages officiels django en utilisant des formulaires? - django, django-forms, modelform

Le didacticiel officiel des sondages django est simple, mais il doit gérer les exceptions POST manuellement, ainsi que coder en dur le front-end. Comment obtenir le même résultat en utilisant des formulaires ?

@csrf_protect
def vote(request, question_id):
p = get_object_or_404(Question, pk=question_id)
if request.method == "GET":
return render(request, "polls/detail.html", {
"question": p,
})
if request.method == "POST":
try:
selected_choice = p.choice_set.get(pk=request.POST["choice"])
except (KeyError, Choice.DoesNotExist):
# Redisplay the question voting form.
return render(request, "polls/detail.html", {
"question": p,
"error_message": "You didn"t select a choice.",
})
else:
selected_choice.votes += 1
selected_choice.save()
return HttpResponseRedirect(reverse("polls:results", args=(p.id,)))



#urls.py
url(r"^(?P<question_id>[0-9]+)/vote/$", views.vote, name="vote"),


#models.py
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField("date published")

def __str__(self):
return self.question_text

def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)


class Choice(models.Model):
question = models.ForeignKey(Question)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)

def __str__(self):
return self.choice_text



# 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>

Je veux faciliter le processus en faisant :

if form.is_valid():
...
votes += 1

et {{ form }} dans les modèles où {{ form }} sont capables de détecter Choice.DoesNotExist et de rendre tout message d'erreur par défaut.

Réponses:

1 pour la réponse № 1

Tout d'abord, vous devez définir un formulaire.La convention est de le faire dans forms.py. Un formulaire est une classe qui hérite de "formulaires". Vous pouvez soit avoir des formulaires.Form, où vous devez définir vous-même votre formulaire, ou des formulaires.ModelForm, qui générera un formulaire basé sur un modèle.

Je vais vous fournir un exemple de modèle de question pour vous aider à démarrer, mais vous devriez lire ceci pour plus d'informations : https://docs.djangoproject.com/en/1.10/topics/forms/

Oh, et si vous cherchez "dans les coulissesmagic", vous pouvez consulter la vue basée sur les classes. Ils gèrent beaucoup de choses pour vous. Ils sont un peu compliqués à personnaliser, mais il existe quelques tutoriels youtube sur le sujet.

Exemple pour les formulaires.ModelForm :

class QuestionForm(forms.ModelForm):

class Meta:
# Define the model here:
model = Question
# Define the fields that you want to show up. Alternatively you can use "exclude", in which you specify the fields that you dont want to show up.
fields = [
"question_text",
"pub_date",
]
# You can use labels to define custom labels.
labels = {
"question_text": "Question Headline",
}

# Specify the widgets you want to use, if they differ from the standard widgets defined by the modelField. This is especialy usefull for ForeignKeys.
#widgets = {
#    "question": forms.HiddenInput,
#}

0 pour la réponse № 2
{##########################################}
{## pollsForm/templates/pollsForm/detail.html#}
{##########################################}
{###pay attention to {{choice_forms}}###}

<h1> {{ question.question_text }}</h1>

<form action="{% url "pollsForm:vote" question.id %}" method="post"> {% csrf_token %}
{{ choice_forms }}
<input type="submit" value="Vote" />
</form>

{##########################################}
{## pollsForm/templates/pollsForm/results.html#}
{##########################################}
{#This is optional page. This is from official tutorial##}
<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 "pollsForm:vote" question.id %}">Vote again?</a>




########################################
# pollsForm/models.py
########################################

same

########################################
# pollsForm/urls.py
########################################

from django.conf.urls import url

from . import views

# namespace="pollsForm"
# append the following line to the myproject/urls.py
#     url(r"^pollsForm/", include("pollsForm.urls", namespace="pollsForm")),

urlpatterns = [
url(r"^(?P<question_id>[0-9]+)/vote/$", views.vote, name="vote"),
url(r"^(?P<pk>[0-9]+)/results/$", views.ResultsView.as_view(), name="results"),
]

########################################
# pollsForm/views.py
########################################

from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.views import generic
from django.views.decorators.csrf import csrf_protect
from .models import Choice, Question
from django import forms
from django.forms import widgets
from .forms import ChoiceForm

@csrf_protect
def vote(request, question_id):
p = get_object_or_404(Question, pk=question_id)
c_set = Choice.objects.filter(question=question_id)

if request.method == "GET":
cforms = ChoiceForm()
cforms.fields["choice_text"] = forms.ModelChoiceField(queryset=c_set,
empty_label=None,
widget=widgets.RadioSelect)
variables = {
"choice_forms": cforms,
"question": p,
}
return render(
request,
"pollsForm/detail.html",
variables,
)

if request.method == "POST":
form = ChoiceForm(request.POST)
if form.is_valid():
pk = form.cleaned_data["choice_text"]
selected_choice = p.choice_set.get(pk=pk)
selected_choice.votes += 1
selected_choice.save()
return HttpResponseRedirect(reverse("pollsForm:results", args=(p.id,)))

if not form.is_valid():
# change input char to radio
form.fields["choice_text"] = forms.ModelChoiceField(queryset=c_set,
empty_label=None,
widget=widgets.RadioSelect)
variables = {
"choice_forms" : form,
"question": p,
}
return render(
request,
"pollsForm/detail.html",
variables,
)

# optional
class ResultsView(generic.DetailView):
model = Question
template_name = "pollsForm/results.html"

Voici un exemple de gestion des formulaires radio en tant que backend.

Il s'agit de l'application pollsForm de manière équivalente à l'application officielle des sondages, mais en utilisant des formulaires au lieu de déranger le front-end. Il génère simplement {{ choice_forms }} au front-end.