Django 使用另一个表中的数据更新表
Posted
技术标签:
【中文标题】Django 使用另一个表中的数据更新表【英文标题】:Django update table using data from another table 【发布时间】:2012-09-13 04:04:24 【问题描述】:我有 2 个表 products
和 catagories
通过外键连接。
我需要使用字段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 使用另一个表中的数据更新表的主要内容,如果未能解决你的问题,请参考以下文章