Django表单向导 - 选择取决于第一个表单步骤

Han*_*nes 5 django dynamic choice formwizard radio-button

我用FormWizard创建了一个2步表单,如下所示:

  • 第一步:询问用户位置
  • 第二步:根据用户位置显示多个搜索结果 ,并将其显示为radioButtons

现在第二种形式取决于第一种形式的输入.一些博客或stackoverflow帖子涵盖了类似的主题,我按照说明操作. 但是,在process_step期间应该保存的变量不可用于下一个_ init _.

如何将变量位置从process_step传递到_ init _?

class reMapStart(forms.Form):
    location = forms.CharField()
    CHOICES = [(x, x) for x in ("cars", "bikes")]
    technology = forms.ChoiceField(choices=CHOICES)

class reMapLocationConfirmation(forms.Form):

   def __init__(self, user, *args, **kwargs):
       super(reMapLocationConfirmation, self).__init__(*args, **kwargs)
       self.fields['locations'] = forms.ChoiceField(widget=RadioSelect(), choices=[(x, x)  for x in location])

class reMapData(forms.Form):
   capacity = forms.IntegerField()

class reMapWizard(FormWizard):
   def process_step(self, request, form, step):
       if step == 1:
          self.extra_context['location'] = form.cleaned_data['location']

   def done(self, request, form_list):
       # Send an email or save to the database, or whatever you want with
       # form parameters in form_list
       return HttpResponseRedirect('/contact/thanks/')
Run Code Online (Sandbox Code Playgroud)

任何帮助都绝对赞赏.

谢谢,H

PS:使用较新的代码更新了帖子.

Yuj*_*ita 10

我想你可以POST直接在你的__init__方法中访问字典,因为它看起来像向导通过POST每个表单实例get_form,但由于某种原因我没有看到数据.

我提出的另一种方法是使用render_template钩子,而不是那么久.

class ContactWizard(FormWizard):
    def done(selef, request, form_list):
        return http.HttpResponse([form.cleaned_data for form in form_list])

    def render_template(self, request, form, previous_fields, step, context=None):
        """
        The class itself is using hidden fields to pass its state, so
        manually grab the location from the hidden fields (step-fieldname)
        """
        if step == 2: 
            locations = Location.objects.filter(location=request.POST.get('1-location'))
            form.fields['locations'].choices = [(x, x) for x in locations]
        return super(ContactWizard, self).render_template(request, form, previous_fields, step, context)
Run Code Online (Sandbox Code Playgroud)


Guy*_*den 6

您可以使用存储对象从任何步骤获取数据:

self.storage.get_step_data('0')
Run Code Online (Sandbox Code Playgroud)

这将返回保存在该特定步骤的存储后端中的数据字典.

在下面的示例中,第一个表单包含一个'Activity'下拉选择.然后,第二个表单包含一个位置选择小部件,该小部件仅显示可用于该活动的位置.

当你向前或向后通过向导时这是有效的 - 如果按'prev',上面的答案不起作用,因为他们只依赖向导(例如,如果你按prev键,POST dict将不包含步骤0的数据)在第3步!)

def get_form(self, step=None, data=None, files=None):

    form = super(EnquiryWizard, self).get_form(step, data, files)
    #print self['forms']['0'].cleaned_data

    step = step or self.steps.current

    if step == '1':
        step_0_data = self.storage.get_step_data('0')
        activity = Activity.objects.get(pk=step_0_data.get('0-activity'))
        locations = Location.objects.filter(activities=activity)
        form.fields['locations'].widget = forms.CheckboxSelectMultiple(choices=[(x.pk,x.name) for x in locations])

    return form
Run Code Online (Sandbox Code Playgroud)