2013-03-29 82 views
1

我想要用自定義字段生成一個表單(簡而言之:某人的某個表單可以響應一系列問題,作爲Quizz的一部分。問題使用Django管理員進行管理,現在我需要一個表單來啓用提交)。Django:自定義字段沒有呈現/未綁定的字段引發錯誤

據我所知,在模板文件中,我應該做一個「在表單中的字段」而不是「在form.fields中的字段」。

然而,通過形式迭代直接返回一個錯誤:「WSGIRequest」對象有沒有屬性「得到」。此錯誤發生在django的data.get()(由field.widget.value_from_datadict()調用)函數中,同時嘗試呈現{{field}}

我明白我正在處理未綁定的字段,但沒有看到我現在做錯了什麼。 關於這個問題的任何線索? 感謝

在forms.py

class ResponseSetForm(forms.Form): 

    def __init__(self, request=None, instance=None, *args, **kwargs): 
     self.title = "TOTO" 
     quizz = kwargs.pop('quizz') 
     super(ResponseSetForm, self).__init__(request, instance, *args, **kwargs) 
     question_list = quizz.mcquestion_set.all().order_by('position') 
     fields={} 
     theChoices=quizz.rating_scale.mcqrating_set.all().order_by('value') 
     choices = ((x.value, x.label) for x in theChoices) 
     for question in question_list: 
      fieldname = 'question_%s' % question.identifier 
      widget = RadioSelect() 
      self.fields[fieldname] = forms.TypedChoiceField(coerce=int, empty_value=None, required=True, label=question.text, choices=choices, widget=widget) 

在views.py

class QuizzView(FormView): 
    http_method_names = ['get', 'post'] 
    template_name = 'test.html' 
    form_class = ResponseSetForm 
    success_url = "/" 

    def get_form_kwargs(self, *args, **kwargs): 
     #used by the form 
     kwargs = super(QuizzView, self).get_form_kwargs() 
     kwargs.update({ 
      'request' : self.request, 
      'quizz' : self.quizz 
     }) 
     return kwargs 

    def dispatch(self, request=None, *args, **kwargs): 
     # parse the request here ie. 
     self.request = request 
     self.quizz = Quizz.objects.prefetch_related('rating_scale', 'mcquestion_set').get(pk=kwargs['pk'])  
     # call the view 
     return super(QuizzView, self).dispatch(request, *args, **kwargs) 
中的test.html模板文件

{% if quizz %} 
<form action="/mcq/2/" method="post">{% csrf_token %} 
    <h2>{{ form.title }} 
    <table> 
     {% for field in form %} 
     <tr> 
      <td>{{ field.label }}</td> 
      <td>{{ field }}</td> 
    </tr> 
     {% endfor %} 
    </table> 
    <p><input type="submit" value="Submit" /></p> 
</form> 
{% else %} 
    <p>No questions are available.</p> 
{% endif %} 

URL模式是:

url(r'^(?P<pk>\d+)', QuizzView.as_view(), name='run_quizz') 

回答

1

好的,所以我發現問題:在整個流程中,表單始終與請求一起初始化(即,無論是GET還是POST)。 因此,窗體被綁定(form.is_bound = True)。

所以我做了什麼: - 落實,設置本身就是一個標誌,呼籲未綁定的形式(我在這裏使用self.kwargs但很可能直接在class屬性使用) 的類get()方法 - 傳達這個標誌通過view.get_form_kwargs() - 在表單中測試標誌。如果設置的話,我也求=無調用超級初始化()之前 - >結果的形式已經self.is_bound =假

我想這將是一個不基於類的視圖更簡單。

這是在代碼方面:

在forms.py

class ResponseSetForm(forms.Form): 

    def __init__(self, request=None, instance=None, *args, **kwargs): 
     try: 
      quizz = kwargs.pop('quizz') 
     except: 
      raise Http404 
     if 'unbound' in kwargs: 
      del kwargs['unbound'] 
      the_request = request 
      request = None 
     super(ResponseSetForm, self).__init__(request, instance, *args, **kwargs) 
     self.title = quizz.name 
     question_list = quizz.mcquestion_set.all().order_by('position') 
     choices=list(((x.value, x.label) for x in quizz.rating_scale.mcqrating_set.all().order_by('value'))) 
     for question in question_list: 
      fieldname = 'question_%s' % question.identifier 
      widget = RadioSelect() 
      self.fields[fieldname] = forms.TypedChoiceField(coerce=int, empty_value=None, required=True, label=question.text, choices=choices, widget=widget) 

在views.py

class QuizzView(FormView): 
    http_method_names = ['get', 'post'] 
    template_name = 'test.html' 
    form_class = ResponseSetForm 
    success_url = "/" 

    def get_form_kwargs(self, *args, **kwargs): 
     # thekwargs used by the form 
     thekwargs = super(QuizzView, self).get_form_kwargs() 
     thekwargs.update({ 
      'request' : self.request, 
      'quizz' : self.quizz 
     }) 
     if 'unbound' in self.kwargs: 
      del self.kwargs['unbound'] 
      thekwargs.update({'unbound': "Yes"}) # we want to let the form know that he is not actually bound 
     return thekwargs 

    def dispatch(self, request=None, *args, **kwargs): 
     # parse the request here ie. 
     self.request = request 
     self.quizz = Quizz.objects.prefetch_related('rating_scale', 'mcquestion_set').get(pk=kwargs['pk']) 
     return super(QuizzView, self).dispatch(request, *args, **kwargs) 

    def get(self, *args, **kwargs): 
     self.kwargs.update({ 
      'unbound' : True, 
     }) 
     # the below call triggers a call to get_form_kwargs (and call to form) 
     return super(QuizzView, self).get(*args, **kwargs) 
+1

在我的情況下,這可能使得基於類的意見不是真的適合比較好的舊功能。 – lai