有什么办法可以保存相互引用两次的模型吗?

joz*_*yqk 4 django django-models

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

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

class One:
    current = models.OneToOneField('Many')
Run Code Online (Sandbox Code Playgroud)

默认情况下,这些具有null=False并且,如果我错了,请纠正我,除非我更改其中一种关系,否则不可能使用这些:

    current = models.OneToOneField('Many', null=True)
Run Code Online (Sandbox Code Playgroud)

原因是因为除非模型已保存,否则您无法将模型分配给关系。否则导致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()
Run Code Online (Sandbox Code Playgroud)

这是正确的方法吗,还是有其他方法可以节省两次?

spe*_*ras 5

没有办法解决这个问题,无论如何你都需要保存其中一个对象两次。

\n\n

这是因为,在数据库级别,您需要保存对象才能获取其 ID。没有办法告诉 sql 数据库“保存这两个对象并将 id 分配给另一个对象上的这些字段”。因此,如果您要手动执行此操作,您将 INSERT 第一个对象的 FK 为 NULL,获取其 ID,INSERT 第二个对象的第一个对象的 ID,获取其 ID,然后更新要设置的第一个对象FK。\n您可以将整个事情封装在一个事务中。

\n\n

因此,您使用 ORM 所做的事情是您能得到的最接近的结果。您可能需要添加以下内容:

\n\n

1)使用事务进行更改,如下所示:

\n\n
from django.db import transaction\n\nwith transaction.atomic():\n    many, one = Many(), One()\n    one.save()\n    many.owner = one\n    many.save()\n    one.current = many\n    one.save(update_fields=[\'current\']) #\xc2\xa0slight optimization here\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

您可能想要检查代码在稍后读取数据库时的反应,如果出于某种原因(手动编辑、有缺陷的插入某处,...)one.current.owner != one

\n