Django ORM 不会从保存的对象刷新外键
Posted
技术标签:
【中文标题】Django ORM 不会从保存的对象刷新外键【英文标题】:Django ORM does not refresh foreign key from saved object 【发布时间】:2017-03-17 06:22:32 【问题描述】:更新对象中的外键后,相关对象不会刷新。
模型.py:
class Name(models.Model):
name = models.CharField(max_length=30, unique=True)
status = models.ForeignKey( 'NameStatus' )
class NameStatus(models.Model):
status = models.CharField(max_length=30, unique=True)
测试它:
>>> name_obj = Name.objects.exclude(name="Foo").get()
>>> print ( status.status.id )
2
>>> name_obj.status_id = status.status.id + 1
>>> print ( "%d vs %d" % (status.status.id, status.status_id )
2 vs 3
样本数据:
姓名:
| id | name | status (status_id) |
----------------------------------
| 1 | Foo | 2 |
| 2 | Bar | 3 |
状态:
| id | status |
----------------------
| 1 | First Status |
| 2 | Second Status |
| 3 | Third Status |
我错过了什么?
是否应该在刷新对象的查询设置中再次调用 .get()?
我知道这可能是为了减少对数据库的不必要调用,但是如何避免呢?
有了这个示例数据,我如何在 Django orm 中将外键从 Second Status 移动到 Third Status。
PS:正如下面的一些答案试图争辩说 field_id 属性不存在或者它会创建一个新的对象属性。这个不对。它在调试器下进行了测试,并且 save() 确实在数据库中反映了它。 _id 文档参考为:https://docs.djangoproject.com/en/1.10/ref/models/fields/#database-representation
编辑:将状态对象更改为名称以反映类权限。添加了示例数据。
【问题讨论】:
为什么要添加一个新的键 status_id 来命名对象(因为模型中没有定义相同的字段)? 因为 Django 是这样命名数据库中 Name 表中的 status 字段的:status_id。这是处理它的错误方式(tm)吗? 首先你的对象命名约定有问题。 已按照您的建议进行编辑以反映对象名称。 【参考方案1】:重写你的测试语句:
>>> name_obj = Name.objects.exclude(name="Foo").get()
>>> print ( name_obj.status.id )
2
>>> name_obj.status.id = name_obj.status.id + 1
>>> print ( "%d vs %d" % (name_obj.status.id, name_obj.id)
预期答案:3 对 2
【讨论】:
name_obj.id 和 name_obj.status_id 是不同的字段。 但是在 django orm 中你是如何读取外键的。不要与实际的 db 列混淆。上面的就可以了,试一试吧。 添加了一些示例数据并按照您的建议重命名了对象变量以使其清晰。 它仍然与我的答案不同。和我的一样。 完成。不过,name_obj.status.id 和 name_obj.id 是不同表的 pk。【参考方案2】:我相信你在这里做了两件不同的事情。
使用 status.status.id,您可以处理对象的数据库 ID。 使用 status.status_id,您可以“即时”创建一个新的对象属性 status_id 并将值 3 分配给它前者与后者无关,所以它们可以有不同的值
例如,你可以这样做:
from .models import Name
status = Name.objects.exclude(name="Foo").get()
status.status.foo = 'bar'
结果如下:status.status.foo 会给你'bar'。
【讨论】:
你确定吗?据我了解, status.status.id 是状态表的 pk 而不是名称表的 pk。使用这个逻辑,对象的数据库 id 就是 status.id。 是的,status.status.id是状态表的pk。 status.status_id 是 Name 对象的一个属性(在此示例中,它也被误导性地称为 status)。如果从查询集中检索的对象(它是一个名称对象)将被称为名称会更清楚。然后 name.status.id 为您提供相关状态对象的 id (pk),name.status_id 是在 name 对象上动态定义的属性。 修正了名称。关于_id,你错了:docs.djangoproject.com/en/1.10/ref/models/fields/… 我查过了。而且我仍然相信我写的是正确的:您可以使用 status_id 来处理值,但不能分配它。相反,我相信在为 name_obj.status_id 赋值时,会在 name_obj 上创建一个名为 status_id 的新属性,而不是在相关的状态 obj 上。我复制了它并得到了与您一样的确切保存结果:name_obj.status.id 给了我 2,而 name_obj.status_id 给了我 3。 我查过了。我相信在为 name_obj.status_id 赋值时,我们在 name_obj 实例上定义了一个新的实例属性。这会覆盖具有相同名称的类属性。以上是关于Django ORM 不会从保存的对象刷新外键的主要内容,如果未能解决你的问题,请参考以下文章