2017-04-12 24 views
0

官方的django民意調查教程很簡單,但它必須手動處理POST異常,以及硬編碼前端。如何通過使用表單來獲得相同的結果?如何通過使用表單等效地實現官方django民意調查的例子?

@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,默認情況下提供任何錯誤消息的模板。

回答

0
{##########################################} 
{## 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}}到前端。

1

首先你必須定義一個表單。公約就是在forms.py中做到這一點。表單是從「表單」繼承的類。你可以有forms.Form,你必須自己定義你的表單,或者forms.ModelForm,它將根據模型生成一個表單。

我會提供一個例子問題的模型,讓你開始,但你應該閱讀更多的投入:https://docs.djangoproject.com/en/1.10/topics/forms/

哦,如果你正在尋找「幕後法寶」你可以看看基於類的視圖。他們爲你處理很多。他們的定製有點複雜,但這個話題有幾個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, 
    #}