Django 使用另一个表中的数据更新表

Posted

技术标签:

【中文标题】Django 使用另一个表中的数据更新表【英文标题】:Django update table using data from another table 【发布时间】:2012-09-13 04:04:24 【问题描述】:

我有 2 个表 productscatagories 通过外键连接。 我需要使用字段catagories.price_markup 更新字段products.new_cost,如下所示:

UPDATE products p
INNER JOIN categories c ON p.category_id = c.id
SET p.new_cost = ROUND(p.pleer_cost * (1 + c.price_markup/100), -1)
WHERE p.update = 1

在 SQL 中这很容易,但是如何使用 Django ORM 来做到这一点?

我的简化尝试不起作用Cannot resolve keyword 'category.price_markup' into field.

Product.actived.select_related('category').filter(update=1)).update(new_cost=F('pleer_cost') * F('category.price_markup'))

【问题讨论】:

【参考方案1】:

你不能使用 F,但是你可以使用 Subquery 和 OuterRef:

from django.db.models import Subquery, OuterRef

cost = Category.objects.filter(
    id=OuterRef('category_id')
).values_list(
    'price_markup'
)[:1]

Product.objects.update(
    new_cost=Subquery(cost)
)

【讨论】:

据我了解这两个模型之间的关系,我建议成本查询过滤器类似于 id=OuterRef('category_id') 仅作记录,这在 Django 1.7 中是不可能的 如果主键在被引用的表上而不是目标上怎么办? @jbodily 您可以像这样使用 Product.objects.update(new_cost=Subquery(Category.objects.values_list('price_marup')[:1])) 但是所有产品都将具有相同的 new_cost 【参考方案2】:

注意:我的答案现在已经过时了,Django 1.11 introduced OuterRef 实现了这个功能。检查 Andrey Berenda 的答案。

根据documentation,不支持使用join子句的更新,见:

但是,与 filter 和 exclude 子句中的 F() 对象不同,您不能 在更新中使用 F() 对象时引入连接——你只能 参考正在更新的模型的本地字段。如果您尝试 引入与 F() 对象的连接,将引发 FieldError:

# THIS WILL RAISE A FieldError
>>> Entry.objects.update(headline=F('blog__name'))

另外,根据这个issue,这是设计使然,近期内没有改变的计划:

这里的实际问题似乎是加入的 F() 子句不是 update() 语句中允许。这是设计使然;支持连接 in update() 子句由于固有的原因被显式删除 在一般情况下支持它们的复杂性。

【讨论】:

是的,你是对的,但是解决方案是存在的,请看下面我的回答 @AndreyBerenda 我的答案早于 Django 1.11,但我认为它对于坚持使用 Django 1.11 的人仍然有效,我将编辑答案以将其指向我们的答案,谢谢。 如果您使用的是较旧的 Django,那么 (a) 您应该升级,但是 (b) 您可以使用反向端口 django-subquery:pypi.org/project/django-subquery【参考方案3】:
rows = Product.objects.filter(old_field__isnull=False)
for row in rows:
     row.new_field = row.old_field.subfield
Product.objects.bulk_update(rows, ['new_field'])

【讨论】:

以上是关于Django 使用另一个表中的数据更新表的主要内容,如果未能解决你的问题,请参考以下文章

postgres,使用另一个表中的数据进行批量更新

mysql更新一个表不在另一个表中的数据

使用 JPA 的概念,如何使用另一个表中的数据更新表?

使用另一个表中的数据更新一个表的记录

Oracle SQL:使用另一个表中的数据更新表

我可以使用未知数据根据另一个表中的数据更新 SQL 表吗? [关闭]