django 1.3+中内联formset的formset

时间:2011-10-04 07:54:32

标签: django inline-formset django-forms

我有一个产品型号和一个价格模型。价格模型对产品型号有FK。可能有多个价格(取决于销售的单位数量)。 django 1.2.5 http://yergler.net/blog/2009/09/27/nested-formsets-with-django/之前会解决这个问题。但正如详细http://www.mail-archive.com/django-users@googlegroups.com/msg124195.html,这不再适用。

结束所需结果:以下表格编辑和添加数据。

产品一 - 价格一,数量 - 价格二,数量 产品二 - 价格一,数量 产品三 - 价格一,数量 - 价格二,数量 - 价格三,数量

为清晰起见而转载:

在Nathan的原始代码中, 最低级别的formset创建如下:

TenantFormset(data=self.data,
              instance=instance,
              prefix='TENANTS_%s' % pk_value)

其中instance是Building的实例,“父”或容器 对于租户和自我来说是

的一个例子
class BaseBuildingFormset(BaseInlineFormSet)

实例化如下:

BuildingFormset = inlineformset_factory(models.Block,
                                        models.Building,
                                        formset=BaseBuildingFormset,
                                        extra=1)

为了解决这个问题,我停止了传递self.data, 这导致了最低的形式 即使在渲染之后,图层也始终具有is_bound = False 张贴回视图。因此验证总是失败而且 表单所代表的对象无法更新。我转载了 使用Nathan的博客文章中的代码的行为,所以似乎 嵌套表单集的这种方法不再有效,或者代码需要 调整工作在1.3。

直到Django 1.2.5,Nathan的代码运行良好。但是在1.3,如果self.data 传递给TenantFormset,结果是空的和ValidationError 是因为尚未提供ManagementForm信息而引发的 这是#11418,AFAICT的预期后果。

有没有人对如何使其工作有任何其他想法?

干杯,

(很抱歉没有详细的代码示例 - 内森的帖子很多 比我的代码更清晰,所以我建议你看一下。)

一般注意:关于如何执行此操作似乎有很多困惑,这里的回复显示http://www.reddit.com/r/django/comments/hwyto/is_there_a_way_to_do_nested_formsets_in_django/

3 个答案:

答案 0 :(得分:2)

正如django docs所说,如果表单没有绑定,则必须传递data = None:

data = None
if self.data:
    data = self.data
form.nested = [ModelXYFormset(data=data, instance = instance, prefix = 'opt%s' % pk_value)]

答案 1 :(得分:0)

我目前正在尝试同样的事情。我从Nathan的代码中实现了相同的解决方案,但遇到了ValidationError问题。转换我们的Django 1.3更新了formset的工作方式,如here所示。所以对于我的代码,

TenantFormset(data=self.data, instance=instance, prefix='TENANTS_%s' % pk_value)

变为

TenantFormset(instance=instance, prefix='TENANTS_%s' % pk_value)

但是我仍然会得到一张空白的表格。

答案 2 :(得分:0)

这是一个解决方案,似乎可以使子子表单验证。

在BaseBuildingFormset中:

def is_valid(self):
    result = super(BaseProtocolEventFormSet, self).is_valid()

    for form in self.forms:
        if hasattr(form, 'nested'):
            for n in form.nested:
                n.data = form.data
                if form.is_bound:
                    n.is_bound = True
                for nform in n:
                    nform.data = form.data
                    if form.is_bound:
                        nform.is_bound = True
                # make sure each nested formset is valid as well
                result = result and n.is_valid()
    return result

每个表单和表单集的数据应该相同(完整的POST数据)。在这里,我们手动设置这个没有得到它的表单。我们还可以看到,在BaseForm类中,is_bound只是验证表单是否包含数据或文件,因此一旦表单有数据,我们就将其设置为true。