django 1.3向导改变form_list以改变后续步骤

时间:2011-09-18 18:24:16

标签: django

我有一个包含formA,form,formS和formS的向导。如果FormA属性名称不为null,我想跳过FormB。我怎么能这样做?

的问候,

3 个答案:

答案 0 :(得分:3)

创建一个视图,有条件地检查当前正在提交的流程的哪个步骤,然后验证表单并选择接下来的表单。

<强> forms.py

class BaseForm(forms.Form)
    # All our forms will have a hidden field identifying them as either A, B or C
    type = forms.HiddenField(...)

class formA(BaseForm)
    # These are the rest of your attibutes (such as 'name' etc.)
    a_1 = forms.TextField(...)
    a_2 = forms.TextField(...)

class formB(BaseForm)
    b_1 = forms.TextField(...)
    b_2 = forms.TextField(...)
    ....

class formC(BaseForm)
    c_1 = forms.TextField(...)
    c_1 = forms.TextField(...)

<强> views.py

可以从URL / form-wizard /调用此视图,并确定它接收的三种表单中的哪一种以及它将为下一步提供的表单。收集完所有数据后,可以执行一些重定向或进一步的逻辑。

def form_wizard(self, request):
    next_form = None
    curr_form = None
    if request.method=='POST':
        # Find out if we have received a form in our chain
        type = request.POST.get("type", None)
        if type == 'a':
            # We are now processing Form A
            curr_form = FormA(request.POST)
            if curr_form.is_valid():
                # Do a check on the attributes (i.e. name==None)
                if curr_form.cleaned_data.get('a_1',None):
                    next_form = FormB()
                    # Now set the value of type to 'b' for the next form
                    next_form.fields['type'].initial = 'b'
                else:
                    next_form = FormC()
                    next_form.fields['type'].initial = 'c'
        elif type == 'b':
            # Processing B
            curr_form = FormB(request.POST)
            if form.is_valid():
                # Do something with this form
                .... 
                next_form = FormC()
                next_form.fields['type'].initial = 'c'
        elif type == 'c':
             # Processing C
             curr_form = FormC(request.POST)
             if curr_form.is_valid():
             # Last form in chain; either redirect or do something else
             return HttpResponseRedirect(...)
        else:
            # First visit to the wizard, give them the first form
            curr_form = FormA()
            curr_form.fields['type'].initial = 'b'

    return .... {'form':curr_form}

最后,在您的模板中:

<强> template.html

这将呈现我们传递给模板的任何形式(A,B或C)

...
<form action="/form-wizard/" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
...

您可能面临的另一个问题是,在您成功完成第三个表单之前,如何保留第一个表单中的数据。通过使用Django的内置会话处理在用户会话中保存第一个表单中的任何有效表单字段,可以轻松克服这个问题:

https://docs.djangoproject.com/en/dev/topics/http/sessions/#examples

答案 1 :(得分:2)

已为Django 1.4重写django.contrib.formtools.wizard应用。新应用程序已被反向移植为django-formwizard,可用于Django 1.3。

如果您正在编写新的formwizard视图,我建议您使用 django-formwizard 应用程序。当旧的formwizard代码被弃用时,这将使得更容易迁移到Django的未来版本。

Django文档中有一节介绍Django的开发版本,描述了如何skip specific steps形式向导。

答案 2 :(得分:2)

如果您坚持使用1.3,FormWizard.process_step就是您正在寻找的钩子。

从文档中,您可以使用此方法:

  

根据以前提交的表单动态更改self.form_list。

一个简单的实现是:

def process_step(self, request, form, step):
  if step == 1 && form.cleaned_data['name'] is not None:
    self.form_list.pop(2)