我正在尝试使用自定义字段生成一个表单(简而言之:一个表单可以回复一系列问题,一部分是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(r'^(?P<pk>\d+)', QuizzView.as_view(), name='run_quizz')
答案 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)