1

カスタムフィールドで生成されたフォームを作成しようとしています(一言で言えば、クイズの一部である一連の質問に回答するためのフォームです。クイズの質問はDjango管理者を使用して管理されています。フォームが必要ですその上で送信を有効にします)。

テンプレート ファイルでは、「form.fields のフィールド」ではなく「フォームのフィールド」を実行する必要があることを理解しています。

ただし、フォームを直接反復するとエラーが返されます: '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')
4

1 に答える 1

1

OK、問題が見つかりました。このフロー全体で、フォームは常にリクエストで初期化されます (つまり、GET か POST かに関係なく)。その結果、フォームはバインドされます (form.is_bound = True)。

だから私がしたこと: - フォームの非バインドを呼び出すフラグを設定するクラス get() メソッドを実装します (ここでは self.kwargs を使用しますが、クラス属性を直接使用することもできます) - このフラグをフォームに伝えますview.get_form_kwargs() を介して - フォーム内でフラグをテストします。設定されている場合、スーパー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 に答える