使用modelformset保存manytomanyfield

时间:2012-02-05 07:03:37

标签: django manytomanyfield django-forms formset

我有一个与另一个模型有很多关系的模型。它们都有与之相关的形式,后者有形式。

 class Foo(models.Model):
   name = models.CharField(max_length=20)
   bars = models.ManyToManyField("Bar",blank=True,null=True)

 class Bar(models.Model):
   name = models.CharField(max_length=20)

 class FooForm(ModelForm):
   class Meta:
     model = Foo

 class BarForm(ModelForm):
   class Meta:
     model = Bar

 BarFormSet = modelformset_factory(Bar,form=BarForm,extra=2)

在我的视图/模板中,标准的ManyToManyField小部件将替换为formset。因此,我必须手动将该formset中指定的Bar实例与Foo的ManyToManyField相关联。我在Foo的干净方法中这样做:

 def clean(self,*arg,**kwargs):
   cleaned_data = self.cleaned_data
   # barSubFormInstance is the BarSubForm that is displayed in my view
   if barFormSetInstance.is_valid(): 
     barInstances = barFormSetInstance.save()
     cleaned_data["bars"] = barInstances
   return cleaned_data

几乎有效。问题是它将Foo.bars设置为formset中已更改的表单集。因此,如果我向我的foo添加一个条形图,然后重新加载表单并添加第二个条形图,foo最多只有第二个条形图。

根据Django文档:

  

save()方法返回已保存到数据库的实例。如果给定实例的数据在绑定数据中没有更改,则实例将不会保存到数据库中,并且不会包含在返回值中...

所以我理解为什么我的代码失败了。我只是不知道该怎么办。我可以传递给cleaning_data [“bars”]哪些会添加新修改的表单但不删除现有的表单?

非常感谢你的帮助。

1 个答案:

答案 0 :(得分:0)

对于它的价值,上述评论中有错误。还有一些我遗漏的细节。

适当的代码如下所示:

def clean(self,*arg,**kwargs):
   cleaned_data = self.cleaned_data
   # barFormSetInstance is the BarFormSet that is displayed in my view
   # it's already been validated by the time this function is called
   barInstances = [form.save() for form in barFormSetInstance if form.cleaned_data]
   cleaned_data["bars"] = barInstances
   return cleaned_data

我还必须确保ManyToManyField的“blank”和“null”都设置为True。 (我不确定为什么我必须这样做而不是覆盖该字段的is_valid()方法才能返回True)。