Django F 表达式加入字段

Posted

技术标签:

【中文标题】Django F 表达式加入字段【英文标题】:Django F expressions joined field 【发布时间】:2014-02-21 17:24:26 【问题描述】:

所以我试图通过运行以下命令来更新我的模型:

FooBar.objects.filter(something=True).update(foobar=F('foo__bar'))

但我收到以下错误:

FieldError: Joined field references are not permitted in this query

如果 F 表达式不允许这样做...我该如何实现此更新?

门票

鉴于this ticket 中的信息,我现在明白这是不可能的,并且永远不会在 django 中实现,但是有没有办法实现这个更新?也许有一些解决方法?我不想使用循环,因为有超过一千万个FooBar 对象,所以 SQL 比 python 快得多。

【问题讨论】:

【参考方案1】:

Django 1.11 增加了对子查询的支持。你应该能够做到:

from django.db.models import Subquery, OuterRef

FooBar.objects.filter(something=True).update(
    foobar=Subquery(FooBar.objects.filter(pk=OuterRef('pk')).values('foo__bar')[:1])
)

【讨论】:

这应该设置为接受的答案。很有帮助,谢谢! 不,它对我不起作用。我收到了这个错误:django.db.utils.OperationalError: (1093, "You can't specify target table 'xxx' for update in FROM 子句")【参考方案2】:

为什么不在这里使用原始 sql: 基于this,它将类似于

from django.db import connection

raw_query = '''
update app_foobar set app_foobar.foobar = 
(select app_foo.bar from app_foo where app_foo.id = app_foobar.foo_id) 
where app_foobar.something = 1; 
'''

cursor = connection.cursor()
cursor.execute(raw_query)

【讨论】:

这是另一种方法:"""UPDATE app_foobar b SET mycol = foo.othercol FROM app_foo a WHERE a.id = b.foo_id""".【参考方案3】:

这是 Georgi Yanchev 对两个模型的回答的实现:

class Foo(models.Model):
    bar = models.ForeignKey(Bar)

Foo.objects \
    .filter(foo_field_1=True) \
    .update(foo_field_2=Subquery(
        Bar.objects \
            .filter(id=OuterRef('bar_id')) \
            .values('bar_field_1')[:1]))

【讨论】:

pk=OuterRef('bar') 而不是 id=OuterRef('bar_id') 对我来说效果很好,我更喜欢它,因为它只使用模型的属性 (bar) 而不是 Django 的内部属性 (bar_id)。跨度> 【参考方案4】:

对于任何想要一种更简单的方法并且没有大量对象的情况的人来说,下面的 sn-p 应该可以正常工作:

for fooBar in FooBar.objects.filter(something=True):
    fooBar.foobar = fooBar.foo.bar
    fooBar.save(update_fields=['foobar'])

对于常规用例,这不应该带来太大的性能差异,尤其是在作为数据迁移的一部分运行时。 如果需要进一步优化,您也可以选择使用select_related

【讨论】:

以上是关于Django F 表达式加入字段的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Django F 表达式中将日期和时间字段合并到 DateTime 字段中

Django F()表达式

Django 的 F() 表达式奇怪行为

django F表达式生成的SQL查询

使用 F 和 Q 表达式进行 Django 模型过滤

字段中的 Django 正则表达式