Django:同时保存多个模型表单(复杂情况)

Django:同时保存多个模型表单(复杂情况),django,django-queryset,modelform,Django,Django Queryset,Modelform,嗯,这可能是一个简单的案例,但我很难弄清楚 我有两个用户注册漏斗(公司和其他人)。当公司用户通过我的注册表单创建用户实例时,我还希望他们输入创建相关实例的辅助表单(基于网站和组织联系人模型) 我知道如何通过发出额外的同步或异步请求来解决这个问题,但我希望用户填写这三个表单,然后单击提交 我这里的问题是,其他两个表单依赖于用户外键作为字段。我创建了字段“null=True,blank=True”,这样我就可以在不使用外键的情况下验证和保存表单,但我最终希望将该键添加到两个模型实例中 我认为我可以验

嗯,这可能是一个简单的案例,但我很难弄清楚

我有两个用户注册漏斗(公司和其他人)。当公司用户通过我的注册表单创建用户实例时,我还希望他们输入创建相关实例的辅助表单(基于网站和组织联系人模型)

我知道如何通过发出额外的同步或异步请求来解决这个问题,但我希望用户填写这三个表单,然后单击提交

我这里的问题是,其他两个表单依赖于用户外键作为字段。我创建了字段“null=True,blank=True”,这样我就可以在不使用外键的情况下验证和保存表单,但我最终希望将该键添加到两个模型实例中

我认为我可以验证这三个表单,保存UserForm,然后使用模型queryset返回新的User.id(都在一个视图中)。然后,我会将该user\u id值添加到另外两个表单字典(WebsiteForm和Organization\u ContactForm)

其工作原理如下:

def register_company(request):
    if request.method=='POST'
       uform=UserCreationForm(request.POST, prefix='user')
       sform=SiteForm(request.POST, prefix='site')
       oform=OrgForm(request.POST, prefix='site')
       if uform.is_valid() and sform.is_valid() and oform.is_valid():
            uform.save()
            user=User.objects.get(email__iexact=uform.cleaned_data['email'])
            uid=unicode(user.id)
       #now I'd add uid back into the SiteForm and Orgform dictionaries and then save both instances              
问题: 1) 不确定是否可以保存模型表单,然后在单个视图中将该模型实例作为查询集返回

2) 我说我不确定,因为我无法解决试图将变量传递给queryset的问题

get manager方法似乎不接受那里的变量。我也这么认为,因为我传递了一个等价的硬编码字符串,它工作了

好的,所以我考虑创建一个新的管理器方法(email),它接受一个变量参数(清理的email字段),然后重试保存一个模型表单、检索模型id数据和保存其他模型表单的过程

我还认为我可以通过一个post save信号来处理这个问题


这里的大致方向会很有帮助。我需要一个起点。

这些都是
ModelForm
s吗

if request.method=='POST'
   uform=UserCreationForm(request.POST, prefix='user')
   sform=SiteForm(request.POST, prefix='site')
   oform=OrgForm(request.POST, prefix='site')
   if uform.is_valid() and sform.is_valid() and oform.is_valid():
        # save returns the object 
        user = uform.save()

        # commit = false doesn't save to DB.
        site = sform.save(commit=False)
        site.user = user
        site.save()

        org = oform.save(commit=False)
        org.user = user
        org.save()
关于注释的更新:当您可以在一个地方进行表单保存时,为什么要将此表单保存逻辑传播到多个区域和文件(信号、表单保存)


代码更具可读性,甚至可以保存代码行。除非它将在全球范围内使用。

我会这样做:

def register_company(request):
    uform=UserCreationForm(request.POST or None, prefix='user')
    sform=SiteForm(request.POST or None, prefix='site')
    oform=OrgForm(request.POST or None, prefix='site')

    if request.POST and all((uform.is_valid(), sform.is_valid(), oform.is_valid()):
        user = uform.save()
        sform.save(user)
        oform.save(user)

    ruturn ...

class UserCreateionForm(ModelForm):
    Meta:
        model = User

class SiteForm(ModelForm):
    Meta:
        model=Site
        exclude=['user', ]

    def save(self, user, commit=True):
        self.instance.user = user
        return super(SiteForm, self).save(commit=commit)

对不起,我花了很长时间解释这个一般性问题,所以略过了代码。是的,这些都是模型表单,而且所讨论的视图显然超出了org.save()。对不起,这不能解决您的问题吗?你说的
#现在我要将uid添加回SiteForm和Orgform字典,然后保存这两个实例
。这是一种更好的方法:)让表单尽其所能,然后直接设置用户,而不是修改传递到这两个表单中的POST dictionary。我认为我应该保存所有三个modelforms,然后发送一个带有回调的POST save信号,该回调从新用户实例获取用户id,并更新其他两个新模型实例(Org和Site)。这合理吗?或者我可以在同一个视图中保存和查询(这是否更可取)?对于一个简单的问题,这听起来像是一个复杂的解决方案!我当然更喜欢复制和粘贴上面的代码,而不是将这种逻辑传播到视图之外。保存
UserCreationModelForm
时已返回一个用户实例,请使用它!如果必须查询用户表才能再次获取实例,为什么要使用用户ID?天哪,斯基尔勋爵,你让我想跳出我的窗口。我甚至从未考虑过save可以将实例作为参数。我只见过“commit=False”参数。哦,如果是真的,那太简单了。它不能,但你可以定义你的保存方法来实现。在Meta中,您使用
exclude=['user',]
,因为没有这一行,您的表单将无法验证,并将绘制用户选择框。对,所以我知道exclude,实际上我对您的解决方案感到非常兴奋,以至于我没有低头查看覆盖的save方法就匆忙尝试了它。我熟悉的。我现在要试一试。顺便说一句,注意我在if语句中使用了
all(…)
,而不是
。因为在您的示例中,如果第一个表单未验证,其他表单将不会验证,用户将仅看到第一个表单的错误。将其设置为def
save(self,user):