Django 表单向导 - 取决于第一个表单步骤的选择
Posted
技术标签:
【中文标题】Django 表单向导 - 取决于第一个表单步骤的选择【英文标题】:Django form wizard - choices depending on first form step 【发布时间】:2011-06-30 07:25:04 【问题描述】:我使用 FormWizard 创建了一个两步表单,如下所示:
第一步:询问用户位置 第二步:显示多个搜索结果 取决于用户位置,并将其显示为单选按钮现在第二种形式取决于第一种形式的输入。几个博客或 *** 帖子涵盖了类似的主题,我按照说明进行操作。 但是,应该在 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/')
非常感谢任何帮助。
谢谢,
PS:帖子已更新为更新的代码。
【问题讨论】:
【参考方案1】:您可以使用存储对象从任何步骤获取数据:
self.storage.get_step_data('0')
这将返回为该特定步骤保存在存储后端中的数据字典。
在下面的示例中,第一个表单包含一个“活动”下拉选择。然后第二个表单包含一个位置选择小部件,它只显示可用于该活动的位置。
这在您通过向导前进或后退时有效 - 如果您按“prev”,上述答案将不起作用,因为它们仅依赖于前进的向导(即 POST dict 将不包含第 0 步的数据,如果在第 3 步按 prev!)
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
【讨论】:
【参考方案2】:在Yuji的帮助下(谢谢)解决问题后的工作代码是:
class reMapWizard(FormWizard):
def render_template(self, request, form, previous_fields, step, context=None):
if step == 1:
location = request.POST.get('0-location')
address, lat, lng, country = getLocation(location)
form.fields['locations'] = forms.ChoiceField(widget=RadioSelect(), choices = [])
form.fields['locations'].choices = [(x, x) for x in address]
return super(reMapWizard, self).render_template(request, form, previous_fields, step, context)
【讨论】:
只是指出,请不要将我的答案重新发布为您的答案。您应该接受有帮助的答案,并通过代码更新来编辑您的问题。【参考方案3】:我认为您可以直接在您的 __init__
方法中访问 POST
字典,因为看起来向导通过 get_form
将 POST
传递到每个表单实例中,但我看不到某些数据原因。
我想出的替代方法是使用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)
【讨论】:
以上是关于Django 表单向导 - 取决于第一个表单步骤的选择的主要内容,如果未能解决你的问题,请参考以下文章
如何显示作为最终 django 表单向导步骤输入的所有数据的预览?