我有2个表products
和catagories
通过外键连接。
我需要使用字段products.new_cost
更新字段catagories.price_markup
,如下所示:
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'))
答案 0 :(得分:15)
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()语句中允许。这是设计的;支持连接 在update()子句中由于固有而被显式删除 在一般情况下支持他们的并发症。
答案 1 :(得分:13)
您不能使用F,但可以使用Subquery和OuterRef:
from django.db.models import Subquery, OuterRef
cost = Category.objects.filter(
id=OuterRef('product_id')
).values_list(
'price_markup'
)[:1]
Product.objects.update(
new_cost=Subquery(cost)
)
答案 2 :(得分:0)
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'])
答案 3 :(得分:-2)
AFAIU可以与
协同工作for row in ModelName.objects.filter(old_field__isnull=False):
row.new_field = row.old_field.subfield
row.save()
答案 4 :(得分:-9)
更新:它似乎无法正常运行或已过期。鉴于我在大约6年内没有使用过Django,我建议你看看这个问题的其他答案,而不是这个问题。如果可能的话,我希望这个没有标记并删除,因为我很确定此时它具有误导性并且不再有效(给出-10分)。
Django对相关字段使用__
(双下划线)。将category.price_markup
更改为category__price_markup
,您应该明确。