Python 为什么在将此模型添加到另一个模型之前需要保存此模型?

Python 为什么在将此模型添加到另一个模型之前需要保存此模型?,python,django,models,Python,Django,Models,在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 = C

在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”中的null值违反了not null约束

但我不明白为什么这是个问题。调用
article.save()
时,它应该能够创建产品(并生成一个id)

我可以通过在
块中使用此代码来解决此问题,但
块除外:

product = Component(name=product_name)
product.save()
article.product = product
但这让我担心的原因是,如果
article.save()
失败,它将已经创建了一个新的组件/产品。我希望他们一起成功或失败


有没有一个好方法可以解决这个问题?

Django ManyToManyField的工作方式是创建一个额外的表。假设你有两个模型,模型A和模型B。如果你做了

ModelA.model_b = models.ManyToManyField(ModelB)
Django在幕后实际做的是创建一个表
app_modela_modelb
有三列:
id
model_a_id
model_b_id

记住这个想法。关于ModelB的保存,Django在保存之前不会为其分配ID。从技术上讲,您可以手动为其分配一个ID并避免此问题。看来你让django处理那些完全可以接受的事情

Django在执行M2M时遇到问题。为什么?如果ModelB还没有id,M2M表上的
model\u b\u id
列会显示什么?null
product_id
的错误很可能是M2M字段上的null约束错误,而不是ModelB记录id


如果你想让他们“一起成功”或“一起失败”,也许是时候研究一下交易了。例如,您可以将整个事务包装在事务中,并在部分失败的情况下执行回滚。我个人还没有在这方面做过很多工作,所以希望其他人能在这方面提供帮助。

Django ManyToManyField的工作方式是它创建了一个额外的表。假设你有两个模型,模型A和模型B。如果你做了

ModelA.model_b = models.ManyToManyField(ModelB)
Django在幕后实际做的是创建一个表
app_modela_modelb
有三列:
id
model_a_id
model_b_id

记住这个想法。关于ModelB的保存,Django在保存之前不会为其分配ID。从技术上讲,您可以手动为其分配一个ID并避免此问题。看来你让django处理那些完全可以接受的事情

Django在执行M2M时遇到问题。为什么?如果ModelB还没有id,M2M表上的
model\u b\u id
列会显示什么?null
product_id
的错误很可能是M2M字段上的null约束错误,而不是ModelB记录id


如果你想让他们“一起成功”或“一起失败”,也许是时候研究一下交易了。例如,您可以将整个事务包装在事务中,并在部分失败的情况下执行回滚。我个人还没有在这方面做过很多工作,所以希望其他人能在这方面提供帮助。

您可以通过以下方法解决这个问题:

target_product, created_flag = Component.objects.get_or_create(name=product_name)
article.product = target_product
我非常确定
get\u或\u create()
将设置对象的id(如果必须创建对象的话)


或者,如果您不介意Article表上的空FK关系,您可以将
null=True
添加到定义中。

您可以使用以下方法解决此问题:

target_product, created_flag = Component.objects.get_or_create(name=product_name)
article.product = target_product
我非常确定
get\u或\u create()
将设置对象的id(如果必须创建对象的话)


或者,如果您不介意在Article表中使用空FK关系,您可以将
null=True
添加到定义中。

在事务中包含代码片段没有什么价值,您应该阅读以获得更好的理解。

在事务中包含代码片段没有什么价值,正如您应该阅读以获得更好的理解。

注意:article.product=Component.objects.create(name=product\u name)有点复杂tidier@michael:噢!我不知道我能做到。这至少好一点。注意:article.product=Component.objects.create(name=product\u name)有点tidier@michael:噢!我不知道我能做到。这至少好一点。看起来有很好的记录,我应该删除关于m2m的评论。组件不是m2m字段。这只是一个
外键
。这并不能真正回答为什么不能在文章发布之前创建组件。我之所以提出这个问题,是因为它通常与表单一起工作。执行
modelForm.save()
时,它将创建过程中需要的任何其他对象,并将它们全部保存(除非您有
commit=False
)。无论如何,我想
交易
是一个不错的选择。看起来有很好的文档记录,我应该删除关于m2m的评论。组件不是m2m字段。这只是一个
外键
。这并不能真正回答为什么不能在文章发布之前创建组件。我之所以提出这个问题,是因为它通常与表单一起工作。执行
modelForm.save()
时,它将创建过程中需要的任何其他对象,并将它们全部保存(除非您有
commit=False
)。无论如何,我想
事务
是一个不错的选择。你是对的,但我正在寻找一个根本不涉及事务的解决方案。关于事务的文档看起来很清楚。有什么理由避免使用事务方法吗?你是对的,但我正在寻找一种根本不涉及事务的解决方案。关于事务的文档看起来很清楚。有什么理由避免使用事务方法吗?如果我不关心
created_标志
?是否有一些python语法的优点允许我省略它?可能是逗号,但没有第二个val?下划线很常见: