1

我正在尝试使用自定义字段生成一个表单(简而言之:某人回答一系列问题的表单,是测验的一部分。测验问题是使用 Django 管理员管理的,现在我需要一个表单启用提交)。

我知道在模板文件中我应该做一个“for field in form”而不是“for field in form.fields”。

但是,直接遍历表单会返回错误:'WSGIRequest' object has no attribute 'get'。此错误发生在 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(r'^(?P<pk>\d+)', QuizzView.as_view(), name='run_quizz')
4

1 回答 1

1

好的,所以我发现了问题:在整个流程中,表单始终使用请求进行初始化(即,无论是 GET 还是 POST)。因此,表单被绑定(form.is_bound = True)。

所以我做了什么: - 实现一个类 get() 方法,它为自己设置一个标志来调用表单的未绑定(我在这里使用 self.kwargs,但很可能直接使用类属性) - 将此标志传递给表单通过 view.get_form_kwargs() - 在表单中测试标志。如果设置,那么我在调用 super Init () 之前发出 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)
于 2013-03-29T20:44:43.520 回答