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. Однако ваша база данных может быть способна оптимизировать его.