Django Условное обновление на основе значений внешних ключей / объединенных полей

Я пытаюсь сделать условное обновление на основе значения поля по внешнему ключу. Пример:

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

Допустим, у меня есть набор запросов A. Я хочу обновить has_guardian каждого элемента в A на основе значения age родителя ребенка в одном update. Я пытаюсь сделать следующее

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. Как я понимаю, объединенные поля / преследующие отношения foreignkey не разрешены в updates.

Мне интересно, есть ли другой способ добиться того же самого, например, обновить этот набор запросов в рамках одного вызова update? В моей ситуации есть еще несколько полей, которые я хотел бы проверить, а не просто income здесь, поэтому если я попытаюсь сделать фильтр, затем обновление, количество вызовов будет линейно количеству аргументов, которые я хотел бы отфильтровать/обновить

Заранее спасибо!

Вот модели, которые, как я предполагаю, вы используете:

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.

  • Подзапрос фильтрует первичный ключ pk окружающего запроса с помощью .filter(pk=OuterRef('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-UPDATE. Однако ваша база данных может быть способна оптимизировать его.

Вернуться на верх