1

別のモデルと多対多の関係にあるモデルがあります。どちらにもフォームが関連付けられており、後者にはフォームセットがあります。

 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ウィジェットがフォームセットに置き換えられています。したがって、そのフォームセットで指定された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をフォームセット内の変更されたフォームのセットに設定することです。したがって、fooに1つのバーを追加してから、フォームをリロードして2つ目のバーを追加すると、fooはその2つ目のバーしか持たなくなります。

Djangoのドキュメントによると:

save()メソッドは、データベースに保存されたインスタンスを返します。特定のインスタンスのデータがバインドされたデータで変更されなかった場合、そのインスタンスはデータベースに保存されず、戻り値に含まれません...

だから私は私のコードが失敗する理由を理解しています。どうしたらいいのかわからない。新しく変更されたフォームを追加し、既存のフォームを削除しないcleaned_data ["bars"]に何を渡すことができますか?

助けてくれて本当にありがとうございます。

4

1 に答える 1

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に設定されていることを確認する必要がありました。(Trueを返すためにそのフィールドのis_valid()メソッドをオーバーライドする代わりに、なぜそれをしなければならなかったのかわかりません)。

于 2012-02-08T03:58:42.973 に答える