Django:自定义字段不呈现/未绑定字段引发错误

时间:2013-03-29 12:21:17

标签: django forms rendering custom-fields

我正在尝试使用自定义字段生成一个表单(简而言之:一个表单可以回复一系列问题,一部分是Quizz。Quizz问题是使用Django管理员管理的,现在我需要有一个表格可以提交它。)

据我所知,在模板文件中我应该使用“for form in form”而不是“for form in form.fields”。

但是,迭代 form 会直接返回错误:'WSGIRequest'对象没有属性'get'。在尝试渲染 {{field}} 时,django的data.get()(由field.widget.value_from_datadict()调用)函数发生此错误。

我知道我正在处理未绑定的字段,但是现在看不出我做错了什么。 关于这个问题的任何线索? 感谢

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 个答案:

答案 0 :(得分:1)

好的,所以我发现了这个问题:在整个流程中,表单始终与请求一起初始化(即GET或POST)。 因此,表单被绑定(form.is_bound = True)。

所以我做了什么: - 实现一个类get()方法,该方法设置一个标志来调用表单的未绑定(我在这里使用self.kwargs但可能直接使用class属性) - 通过view.get_form_kwargs()将此标志传递给表单 - 在表格中测试旗帜。如果设置,那么在调用超级初始化() - &gt;之前,我会发出request = None因此表单有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)