如何使用表单等效实现django官方的polls示例?
How to implement the official django polls example equivalently by using forms?
官方的django polls 教程很简单,但是它必须手动处理POST 异常,并且对前端进行硬编码。如何使用表格得到相同的结果?
@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>
我想通过以下方式简化流程:
if form.is_valid():
...
votes += 1
和
{{ form }}
在模板中 {{ form }}
能够检测 Choice.DoesNotExist 并默认呈现任何错误消息。
首先你必须定义一个表单。惯例是在 forms.py 中执行此操作。表单是继承自 "forms" 的 Class。您可以使用 forms.Form,您必须自己定义表单,或者使用 forms.ModelForm,它将根据模型生成表单。
我将提供问题模型的示例以帮助您入门,但您应该阅读此内容以获取更多信息:https://docs.djangoproject.com/en/1.10/topics/forms/
哦,如果您正在寻找 "behind the scenes magic",您可以查看基于 Class 的视图。他们为你处理很多事情。它们的定制有点复杂,但是有一些关于该主题的 youtube 教程。
forms.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,
#}
{##########################################}
{## 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'
这是如何将无线电表单作为后端处理的示例。
这是等同于官方民意调查应用程序的 pollsForm 应用程序,但使用表单而不是搞乱前端。它只是向前端生成 {{ choice_forms }} 。
官方的django polls 教程很简单,但是它必须手动处理POST 异常,并且对前端进行硬编码。如何使用表格得到相同的结果?
@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>
我想通过以下方式简化流程:
if form.is_valid():
...
votes += 1
和
{{ form }}
在模板中 {{ form }}
能够检测 Choice.DoesNotExist 并默认呈现任何错误消息。
首先你必须定义一个表单。惯例是在 forms.py 中执行此操作。表单是继承自 "forms" 的 Class。您可以使用 forms.Form,您必须自己定义表单,或者使用 forms.ModelForm,它将根据模型生成表单。
我将提供问题模型的示例以帮助您入门,但您应该阅读此内容以获取更多信息:https://docs.djangoproject.com/en/1.10/topics/forms/
哦,如果您正在寻找 "behind the scenes magic",您可以查看基于 Class 的视图。他们为你处理很多事情。它们的定制有点复杂,但是有一些关于该主题的 youtube 教程。
forms.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,
#}
{##########################################}
{## 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'
这是如何将无线电表单作为后端处理的示例。
这是等同于官方民意调查应用程序的 pollsForm 应用程序,但使用表单而不是搞乱前端。它只是向前端生成 {{ choice_forms }} 。