Pergunta

No Django, eu estou tentando fazer algo como isto:

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

Mas então ele me diz:

valor nulo na coluna "product_id" viola não-nula restrição

Mas eu não entendo por que este é um problema. Quando article.save() é chamado, ele deve ser capaz a criar o produto então (e gerar um id).

Eu posso contornar esse problema usando este código no bloco except:

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

Mas a razão pela qual este me preocupa é porque se article.save() falhar, ele já terá criado um novo componente / produto. Eu quero que eles ter sucesso ou falhar juntos.

Existe uma boa maneira de contornar este problema?

Foi útil?

Solução

Você pode contornar isso usando:

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

como eu tenho certeza que get_or_create() irá definir o ID de um objeto, se tem que criar um.

Como alternativa, se você não se importa as relações FK vazios na mesa de artigo, você pode adicionar null=True para a definição.

Outras dicas

A forma como o Django ManyToManyField funciona é que ele cria uma tabela extra. Então, digamos que você tem dois modelos, ModelA e ModelB. Se você fez ...

ModelA.model_b = models.ManyToManyField(ModelB)

O Django realmente faz nos bastidores é que ele cria uma tabela ... app_modela_modelb com três colunas: id, model_a_id, model_b_id

.

mantenha esse pensamento em sua mente. Em relação à economia de ModelB, Django não atribuir a ela um ID até que seja salva. Você poderia tecnicamente atribuí-lo manualmente um ID e evitar este problema. Parece que você está deixando django pega o que é perfeitamente aceitável.

Django tem um problema, em seguida, fazendo o M2M. Por quê? Se ModelB não tem um ID ainda, o que se passa na coluna model_b_id na mesa de M2M? O erro para product_id nulo é mais do que provável um erro nula restrição no campo M2M, não o ModelB ID de registo.

Se você gostaria que eles "ter sucesso juntos" ou "fracassaremos juntos", talvez tempo de olhar para as transações. Você, por exemplo, enrole a coisa toda em uma transação, e fazer uma reversão no caso de uma falha parcial. Eu não fiz um monte de trabalho pessoalmente nesta área por isso espero que alguém vai ser de assistência sobre o assunto.

Há pouco valor em incluindo um trecho de código sobre as transações, como você deve ler a documentação Django para ganhar um bom entendimento.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top