是否有任何方法可以保存两次相互引用的模型?

时间:2015-06-14 07:57:11

标签: django django-models

我的问题是保存需要互相引用的新模型,而不仅仅是使用related_name查找,例如:

class Many:
    owner = models.ForeignKey('One')

class One:
    current = models.OneToOneField('Many')

默认情况下,这些都有null=False,如果我错了,请纠正我,在我改变其中一种关系之前使用这些是不可能的:

    current = models.OneToOneField('Many', null=True)

原因是因为除非已经保存,否则您无法为关系指定模型。否则会导致ValueError: 'Cannot assign "<...>": "..." instance isn't saved in the database.'

但是现在当我创建一对这些对象时,我需要保存两次:

many = Many()
one = One()
one.save()
many.owner = one
many.save()
one.current = many
one.save()

这是正确的方法,还是有另外一种方法可以保存两次?

1 个答案:

答案 0 :(得分:4)

无法绕过它,无论如何都需要保存其中一个对象。

这是因为,在数据库级别,您需要保存对象以获取其ID。没有办法告诉sql数据库&#34;保存这两个对象并将id分配给另一个对象上的那些字段&#34;。因此,如果您要手动执行此操作,则可以使用NULL为FK插入第一个对象,返回其ID,使用第一个对象插入第二个对象,获取其ID,然后更新第一个要设置的对象FK。 您可以将整个事物封装在事务中。

所以你用ORM做的事情就是你能得到的最接近的。您可能希望在其上添加以下内容:

1)使用交易进行更改,如下所示:

from django.db import transaction

with transaction.atomic():
    many, one = Many(), One()
    one.save()
    many.owner = one
    many.save()
    one.current = many
    one.save(update_fields=['current']) # slight optimization here

2)现在这封装在一个事务中,你想要删除null=True你不能,因为不幸的是,立即检查。 [编辑:似乎Oracle可能支持推迟NOT NULL检查,所以如果你正在使用Oracle,你可以尝试删除null=True,它应该可以工作。]

如果由于某种原因(手动编辑,在某处插入错误,......)one.current.owner != one,您可能希望检查代码在稍后读取数据库时的反应方式。 / p>