Django 1.1 表单向导,动态扩展表单

1 投票
2 回答
1092 浏览
提问于 2025-04-15 17:22

我正在尝试创建一个多页表单,第二页的字段数量是根据第一页的回答来决定的。

我已经设置了一个表单向导(formWizard),我理解我需要使用process_step()来调整下一页的设置。我可以扩展现有的表单定义来添加更多的字段,或者将两个或多个表单定义合并在一起,以产生正确数量的表单元素,但我不知道该怎么做。

举个例子:

第一页 - 选择感兴趣的科目:

第二页 - 针对每个科目:询问相关问题。这些问题在应用程序中被定义为单独的表单,但需要在一页上显示,或者合并成一个表单。

任何帮助都非常感谢。

Spender

2 个回答

0

我觉得这个

self.form_list[1] = RelatedQForm(chosen_subs)

部分不太管用。我总是收到这个错误信息:

object is not callable

看起来 form_list 只接受 RelatedQForm(这个表单的名字),而不是它的一个实例。

1

Spender,

目前我还不知道如何在一个FormWizard页面上合并多个表单。在django 1.2中,你将能够将FormSets作为FormWizards的步骤(具体可以参考这个链接),但那只是处理多个相同表单的副本,而不是多个不同表单的组合。不过,有一种方法可以实现你想要的:

from django.contrib.formtools.wizard import FormWizard
from django import forms

class SubjectForm(forms.Form):
    subjects = forms.MultipleChoiceField(choices = (('language', 'language'), 
                                                        ('sport','sport')))

class RelatedQForm(forms.Form):
    """Overload the __init__ operator to take a list of forms as the first input and generate the 
    fields that way."""
    def __init__(self, interested_subjects, *args, **kwargs):
        super(RelatedQForm, self).__init__(*args, **kwargs)
        for sub in interested_subjects:
            self.field[sub] = forms.CharField(label = "What do you think about %s" % subject)

class SubjectWizard(FormWizard):
    def done(self, request, form_list):
        process_form_list(form_list)

    def process_step(self, request, form, step):
        if step == 1:
            chosen_subs = form.cleaned_data['subjects']
            self.form_list[1] = RelatedQForm(chosen_subs)

使用这段代码,你可以像平常一样在视图中实例化你的FormWizard,然后让向导类在后台处理所有事情。

大致的思路是重载一个名为init的类,叫做“RelatedQForm”,来动态修改字段。这段代码片段来自于这里。你可以在init操作中进行复杂的处理,比如把你的表单字段作为if-elif块放在循环里……你甚至可以想办法从当前表单中程序化地提取字段,不过我得先看看这些表单才能搞明白。

你的“process_form_list”函数需要使用类似下面的方式来循环字段:

for field, val in form.cleaned_data.items():
    do_stuff

希望这能帮助你开始 :)

撰写回答