【发布时间】:2021-09-25 14:36:37
【问题描述】:
假设我有两个模型,我将它们称为 ModelA 和 ModelB。两种模型都有一些共同的字段(由field_one、field_two 和field_three 表示)。此外,ModelB 有一个指向 ModelA 的外键。
class ModelA(Model):
field_one = models.IntegerField()
field_two = models.TextField()
field_three = models.BooleanField()
class ModelB(Model):
field_one = models.IntegerField()
field_two = models.TextField()
field_three = models.BooleanField()
model_a = models.ForeignKey(ModelA, on_delete=models.CASCADE)
我需要更新ModelB 的所有实例以将字段的值更新为关联ModelA 实例的值。我需要完全在数据库中执行此操作,而不需要实例化任何模型实例(不使用.save() 或bulk_update())。
我知道如何在 PostgreSQL 中使用子查询来实现这一点:
UPDATE model_b SET (field_one, field_two, field_three) =
(SELECT field_one, field_two, field_three FROM model_a
WHERE model_b.model_a_id = model_a.id);
如何在 Django 的 ORM 中表达上述查询?
这是我能得到的最接近的:
ModelB.objects.update(
field_one=Subquery(ModelA.objects.filter(id=OuterRef('model_a_id')).values(field_one)[:1]),
field_two=Subquery(ModelA.objects.filter(id=OuterRef('model_a_id')).values(field_two)[:1]),
field_three=Subquery(ModelA.objects.filter(id=OuterRef('model_a_id')).values(field_three)[:1])
})
但是,这会导致每个字段都有一个子查询:
UPDATE model_b SET
field_one = (SELECT model_a.field_one FROM model_a WHERE model_a.id = model_b.model_a_id LIMIT 1),
field_two = (SELECT model_a.field_two FROM model_a WHERE model_a.id = model_b.model_a_id LIMIT 1),
field_three = (SELECT model_a.field_three FROM model_a WHERE model_a.id = model_b.model_a_id LIMIT 1);
【问题讨论】:
-
所以如果你想在一个查询中完成,我认为子查询是唯一的选择。
标签: python django django-queryset django-orm