Domanda

In django, sto provando a fare qualcosa del genere:

# 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 ...

Ma poi mi dice:

  

valore nullo nella colonna " product_id " viola il vincolo non nullo

Ma non capisco perché questo sia un problema. Quando viene chiamato article.save () , dovrebbe essere in grado di creare il prodotto quindi (e generare un ID).

Posso aggirare questo problema utilizzando questo codice nel blocco tranne :

product = Component(name=product_name)
product.save()
article.product = product

Ma la ragione per cui mi preoccupa è perché se article.save () fallisce, avrà già creato un nuovo componente / prodotto. Voglio che abbiano successo o falliscano insieme.

C'è un bel modo per aggirare questo?

È stato utile?

Soluzione

Puoi aggirare il problema usando:

target_product, created_flag = Component.objects.get_or_create(name=product_name)
article.product = target_product

poiché sono abbastanza sicuro che get_or_create () imposterà l'id di un oggetto, se deve crearne uno.

In alternativa, se non ti dispiace relazioni FK vuote nella tabella degli articoli, puoi aggiungere null = True alla definizione.

Altri suggerimenti

Il modo in cui Django ManyToManyField funziona è che crea una tabella aggiuntiva. Quindi supponiamo di avere due modelli, ModelA e ModelB. Se lo facessi ...

ModelA.model_b = models.ManyToManyField(ModelB)

Quello che Django effettivamente fa dietro le quinte è che crea una tabella ... app_modela_modelb con tre colonne: id , model_a_id , model_b_id .

Tieni quel pensiero nella tua mente. Per quanto riguarda il salvataggio di ModelB, Django non gli assegna un ID finché non viene salvato. È possibile tecnicamente assegnargli manualmente un ID ed evitare questo problema. Sembra che stai lasciando che Django gestisca ciò che è perfettamente accettabile.

Django ha un problema a fare M2M. Perché? Se ModelB non ha ancora un ID, cosa succede nella colonna model_b_id sulla tabella M2M? L'errore per null product_id è molto probabilmente un errore di vincolo null nel campo M2M, non nell'ID record ModelB.

Se desideri che " riescano insieme " o " fallire insieme " forse è tempo di esaminare le transazioni. Ad esempio, si avvolge il tutto in una transazione e si esegue un rollback in caso di errore parziale. Non ho svolto molto lavoro personalmente in questo settore, quindi spero che qualcun altro possa essere di aiuto su questo argomento.

C'è poco valore nell'includere un frammento di codice sulle transazioni, come dovresti leggere la documentazione di Django per acquisire una buona comprensione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top