【问题标题】:Django F expressions joined fieldDjango F 表达式加入字段
【发布时间】: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 快得多。

【问题讨论】:

    标签: python sql django


    【解决方案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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-29
      • 1970-01-01
      • 2016-02-13
      • 1970-01-01
      • 2015-08-05
      • 1970-01-01
      • 2019-10-31
      相关资源
      最近更新 更多