基于外键值/连接字段的 Django 条件更新

Django Conditional update based on Foreign key values / joined fields

我正在尝试根据外键字段的值进行条件更新。示例:

Model Kid: id, parent (a foreign key to Parent), has_rich_parent
Model Parent: id, income

假设我有一组 A 的查询。我想根据一个 update 中 Kid 的父项的 age 的值更新 A 中每个项目的 has_guardian。我想做的是

queryset_of_kids.update(
    has_rich_parent=Case(
       When(parent__income__gte=10, then=True)
       default=False
    )
)

但这给我一个错误 Joined field references are not permitted in this query。我将其理解为 updates.

中不允许加入字段/追求外键关系

我想知道是否有任何其他方法可以完成同样的事情,例如在一次更新调用中更新此查询集?我的情况有几个我想验证的字段,而不仅仅是 income 在这里,所以如果我尝试先过滤然后更新,调用次数将与我想要的参数数量成线性关系filter/update.

提前致谢!

以下是我假设您使用的模型:

from django.db import models

class Kid(models.Model):
    parent = models.ForeignKey('Parent', on_delete=models.CASCADE)
    has_rich_parent = models.BooleanField(default=False)

class Parent(models.Model):
    income = models.IntegerField()

您可以使用 Subquery 来更新 has_rich_parent 字段。

  • 子查询使用 .filter(pk=OuterRef('pk')).
  • 对周围查询的主键 pk 进行过滤
  • 它使用Q查询object来获取parent收入是否>=10。
from .models import Kid, Parent
from django.db.models import Q, Subquery, OuterRef

Kid.objects.update(has_rich_parent=Subquery(
    Kid.objects.filter(pk=OuterRef('pk'))
               .values_list(Q(parent__income__gte=10))))

该命令产生以下 SQL 查询:

UPDATE "more_kids_kid"
SET "has_rich_parent" = (
  SELECT (U1."income" >= 10) AS "q1"
  FROM "more_kids_kid" U0
  INNER JOIN "more_kids_parent" U1 ON (U0."parent_id" = U1."id")
  WHERE U0."id" = ("more_kids_kid"."id")
)

此查询不如 SELECT-then-UPDATE 查询有效。但是,您的数据库可能会对其进行优化。