【问题标题】:Django Conditional update based on Foreign key values / joined fields基于外键值/连接字段的 Django 条件更新
【发布时间】:2022-01-21 19:03:14
【问题描述】:

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

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

假设我有一个查询集 A。我想根据孩子的父级 update 中的 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,所以如果我尝试过滤然后更新,调用的数量将与我想要过滤的参数数量成线性关系/更新。

提前致谢!

【问题讨论】:

  • 请更新问题queryset_of_kids
  • 试试When(Greatest(F('parent__income'), 9), then=True) default=False别忘了加from django.db.models import Ffrom django.db.models.functions import Greatest

标签: django django-models


【解决方案1】:

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

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查询对象获取父收入是否>=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 查询高效。但是,您的数据库可能能够对其进行优化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-16
    • 1970-01-01
    • 1970-01-01
    • 2018-07-04
    • 2017-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多