Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/345.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 您能在django中对模型表单使用表单向导吗?_Python_Django_Django Models - Fatal编程技术网

Python 您能在django中对模型表单使用表单向导吗?

Python 您能在django中对模型表单使用表单向导吗?,python,django,django-models,Python,Django,Django Models,我有一个模型,我使用ModelForm从模型中创建了一个表单。现在,我想把表格分成两页。例如,前三个字段将显示在第一页上,然后用户单击next,最后三个字段将显示在第二页上。然后单击submit,用户提交的数据被添加到数据库中 我查看了表单向导的文档,它似乎也适用于模型表单?有人能证实这一点吗 如果是这样,有人能解释一下创建WizardView类的过程吗 文档中给出了这个示例,我不明白后两个参数是什么。form_list只是基于表单类实例化的表单对象列表吗?什么是**kwargs class C

我有一个模型,我使用
ModelForm
从模型中创建了一个表单。现在,我想把表格分成两页。例如,前三个字段将显示在第一页上,然后用户单击next,最后三个字段将显示在第二页上。然后单击submit,用户提交的数据被添加到数据库中

我查看了表单向导的文档,它似乎也适用于模型表单?有人能证实这一点吗

如果是这样,有人能解释一下创建
WizardView
类的过程吗

文档中给出了这个示例,我不明白后两个参数是什么。form_list只是基于表单类实例化的表单对象列表吗?什么是
**kwargs

class ContactWizard(SessionWizardView):
    def done(self, form_list, **kwargs):
        do_something_with_the_form_data(form_list)
        return HttpResponseRedirect('/page-to-redirect-to-when-done/')

提前感谢您的帮助

表单向导正在Django 1.4中内置,所以这是一个很好的方法。它应该做你想做的,但是你可能需要一些调整

现在不要担心
done()
中的
kwargs
,您不需要它们

form\u list
是您希望用于步骤的表单列表-来自
url.py

urlpatterns = patterns('',
    (r'^contact/$', ContactWizard.as_view([ContactForm1, ContactForm2])),
)
[ContactForm1,ContactForm2]
将作为
表单列表传递到
done()

您需要做的是将
ModelForm
分解为单独的表单。要做到这一点,最简单的方法(如果您希望在多个表单上创建模型)是不要使用
ModelForm
,而只创建您自己的表单。这很简单:

from django import forms

class ContactForm1(forms.Form):
    subject = forms.CharField(max_length=100)
    sender = forms.EmailField()

class ContactForm2(forms.Form):
    message = forms.CharField(widget=forms.Textarea)
一旦表单反映了模型的各个部分,只需按照中所述创建
视图
模式
,并将
使用表单数据(表单列表)
做一些事情设置为一个函数,从表单数据完成模型,然后执行保存


您可以使用
ModelForm
,但只有在您能够说服它为表单向导生成用于每个步骤的不同表单时,这将是一个棘手的部分。

假设您的模型有两个字段

class AModel( Model ):
    fieldA = CharField()
    fieldB = CharField()
我们希望使用
FormWizard
在单独的步骤中设置每个字段。因此,我们创建了两个
ModelForm
s,每个显示一个字段:

class Form1( ModelForm ):
    class Meta:
        model = AModel
        fields = ( 'fieldA', )

class Form2( ModelForm ):
    class Meta:
        model = AModel
        fields = ( 'fieldB', )
我们称我们的表单向导为AWizard;
url.py
条目应该如下所示

url( r'^$', AWizard.as_view( [ Form1, Form2 ] ) ),
AWizard
的实现中,我们需要确保所有表单将其数据写入单个实例,然后将其保存到数据库:

class AWizard( SessionWizardView ):
    instance = None

    def get_form_instance( self, step ):
        if self.instance is None:
            self.instance = AModel()
        return self.instance

    def done( self, form_list, **kwargs ):
        self.instance.save()
请注意,我们重写了方法
get\u form\u instance
。此方法返回表单绑定到的模型实例

您可能会认为(我是这样认为的),该方法为第一个请求(向导的第一步)创建了一个实例,然后在所有步骤中继续使用该实例

事实上,这有点复杂。对于每个请求,将创建一个新的
AWizard
实例,该实例将依次创建一个新的
AModel
实例。因此,这些步骤并不共享一个实例

当最后一张表格提交时,奇迹就发生了。此时,所有表单都被重新验证,每个表单调用
get\u form\u实例
,最后填充一个
AModel
实例


然后将该实例保存在
done

由@wuerg提出的观点对我不起作用,我必须这样做:

class AWizard( SessionWizardView ):
    def dispatch(self, request, *args, **kwargs):
        self.instance = AModel()
        return super(ApplyWizard, self).dispatch(request, *args, **kwargs)

    def get_form_instance( self, step ):
        return self.instance

    def done( self, form_list, **kwargs ):
        self.instance.save()
        return HttpResponseRedirect(reverse(thanks))

我不得不改变@wuerg和@madmen的解决方案,以便在我的用例中工作(在每一步之后保存模型)。这种方法的最大优点是它总是使用
AModel
的相同实例,而不是为每个步骤创建新实例:

class AWizard(SessionWizardView):
    instance = AModel()

    def dispatch(self, request, *args, **kwargs):
        return super(AWizard, self).dispatch(request, *args, **kwargs)

    def get_form_instance(self, step):
        return self.instance

    def done(self, form_list, **kwargs):
        self.save_model()
        return render_to_response('done.html')

如果您选择使用
ModelForm
,您可以使用
字段
排除
来控制每个步骤可见的字段。我想在第一个表单的单选按钮上显示我的表单。我该如何做?您能指导我吗?从我的测试来看,此解决方案不起作用。如果您打开另一个窗口来模拟另一个用户并尝试在向导中导航,您将使用同一个实例,因此,您的字段将预先填充第一个用户的数据!这些关于get_form_instance()的信息非常有用!!谢谢