Warum brauche ich dieses Modell zu retten, bevor es zu einem anderen hinzuzufügen?
Frage
In django, ich versuche, so etwas zu tun:
# 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 ...
Aber dann sagt es mir:
Nullwert in der Spalte "product_id" verletzt nicht-NULL-Constraint
Aber ich verstehe nicht, warum das ein Problem ist. Wenn article.save()
genannt wird, soll es in der Lage sein, die das Produkt erstellen und (und erzeugt eine id).
Ich kann mit diesem Code in dem except
Block, um dieses Problem umgehen:
product = Component(name=product_name)
product.save()
article.product = product
Aber der Grund, dies mich betrifft, denn wenn article.save()
ausfällt, wird es bereits eine neue Komponente / Produkt erstellt haben. Ich möchte, dass sie gemeinsam erfolgreich zu sein oder nicht.
Gibt es eine schöne Möglichkeit, dies zu umgehen?
Lösung
Sie können dieses Problem umgehen, indem Sie:
target_product, created_flag = Component.objects.get_or_create(name=product_name)
article.product = target_product
, wie ich bin mir ziemlich sicher, dass get_or_create()
die ID eines Objekts festgelegt wird, wenn es zu erstellen hat.
Alternativ, wenn Sie nicht leer FK Beziehungen auf der Artikel-Tabelle nichts dagegen haben, Sie null=True
die Definition hinzufügen könnten.
Andere Tipps
Die Art und Weise der Django ManyToManyField funktioniert, ist, dass es eine zusätzliche Tabelle erstellt. So sagen, Sie haben zwei Modelle, ModelA und Modell B. Wenn ja ...
ModelA.model_b = models.ManyToManyField(ModelB)
Was Django tatsächlich tut, hinter den Kulissen wird eine Tabelle erstellt, ... app_modela_modelb
mit drei Spalten:. id
, model_a_id
, model_b_id
Halten Sie die in Ihrem Kopf gedacht. Im Hinblick auf die Einsparung von Modell B, ist Django nicht abtreten es sich um eine ID, bis sie gespeichert wird. Sie könnten technisch es manuell eine ID zuweisen und dieses Problem zu vermeiden. Es scheint, du laesst django damit umgehen, was durchaus akzeptabel ist.
Django hat ein Problem, dann die M2M tun. Warum? Wenn Modell B eine ID hat noch nicht, geht, was in der model_b_id
Spalte auf der M2M-Tabelle? Der Fehler für null product_id
ist mehr als wahrscheinlich, ein NULL-Constraint-Fehler auf dem M2M-Bereich, nicht das Modell B Datensatz-ID.
Wenn Sie möchten, dass zu „zusammen erfolgreich“ oder „nicht bestanden zusammen“ vielleicht ist es Zeit, in Transaktionen zu suchen. Sie, zum Beispiel, wickeln Sie das Ganze in einer Transaktion, und ein Rollback im Fall eines teilweisen Ausfalls tun. Ich habe nicht eine ganze Menge Arbeit persönlich in diesem Bereich getan, so hoffentlich jemand andere zu diesem Thema hilfreich sein wird.
Es gibt wenig Wert einen Code-Snippet auf Transaktionen im einschließlich, wie Sie die Django-Dokumentation ein gutes Verständnis zu gewinnen.