2013-03-29 2 views
1

Я пытаюсь создать форму с настраиваемыми полями (в двух словах: форма для ответа на ряд вопросов, часть Quizz. вопросы администрируются с помощью администратора Django, теперь мне нужно иметь форму, чтобы разрешить отправку на нее).Django: настраиваемые поля, не отображающие ошибки при создании/снятии полей

Я понимаю, что в файле шаблона я должен делать «для поля в форме», а не «для поля в form.fields».

Однако переборе формы непосредственно возвращает ошибку: объект «WSGIRequest» не имеет атрибута «получить». Эта ошибка возникает в django's 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 здесь, но также могу непосредственно использовать атрибут класса) - передать этот флаг переходит к форме через view.get_form_kwargs() - проверьте флаг в форме. Если установлено, то я делаю request = None перед вызовом super Init() -> следовательно, форма имеет self.is_bound = False

Я думаю, это было бы проще без класса.

Здесь по коду:

в 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

Смежные вопросы