別のモデルに追加する前にこのモデルを保存する必要があるのはなぜですか?
質問
djangoでは、次のようなことをしようとしています:
# if form is valid ...
article = form.save(commit=False)
article.author = req.user
product_name = form.cleaned_data['product_name']
try:
article.product = Component.objects.get(name=product_name)
except:
article.product = Component(name=product_name)
article.save()
# do some more form processing ...
しかし、それは私に言う:
列" product_id"のヌル値非ヌル制約に違反しています
しかし、なぜこれが問題なのかわかりません。 article.save()
が呼び出されると、製品を then 作成(およびIDを生成)できるはずです。
except
ブロックで次のコードを使用すると、この問題を回避できます。
product = Component(name=product_name)
product.save()
article.product = product
しかし、これが私に関係する理由は、 article.save()
が失敗した場合、すでに新しいコンポーネント/製品を作成しているからです。それらを一緒に成功または失敗させたい。
これを回避する良い方法はありますか?
解決
を使用してこれを回避できます:
target_product, created_flag = Component.objects.get_or_create(name=product_name)
article.product = target_product
オブジェクトを作成する必要がある場合、 get_or_create()
がオブジェクトのIDを設定すると確信しています。
また、Articleテーブルの空のFKリレーションを気にしない場合は、 null = True
を定義に追加できます。
他のヒント
Django ManyToManyFieldの動作方法は、追加のテーブルを作成することです。つまり、ModelAとModelBの2つのモデルがあるとします。もしそうなら...
ModelA.model_b = models.ManyToManyField(ModelB)
Djangoが実際に背後で行うことは、3つの列を持つテーブルを作成することです... app_modela_modelb
: id
、 model_a_id
、 model_b_id
。
その考えを心に留めてください。 ModelBの保存に関して、Djangoは保存されるまでIDを割り当てません。技術的に手動でIDを割り当て、この問題を回避できます。完璧に受け入れられるものをdjangoに処理させているようです。
DjangoにはM2Mの実行に問題があります。どうして? ModelBにまだIDがない場合、M2Mテーブルの model_b_id
列には何が入りますか? null product_id
のエラーは、ModelBレコードIDではなく、M2Mフィールドのnull制約エラーである可能性が高いです。
「一緒に成功」したい場合または「一緒に失敗する」おそらく、トランザクションを調べるときです。たとえば、トランザクション全体をラップし、部分的な障害が発生した場合はロールバックします。私はこの分野で個人的に多くの仕事をしたことがないので、他の誰かがそのトピックの助けになることを願っています。
Djangoのドキュメントを参照して、理解を深めてください。