Django аннотирует условное значение
Допустим, у меня есть такая модель:
class modelA(models.model):
name = models.Charfield()
class modelB(models.model):
model_A = models.ForeignKey('modelA', on_delete=models.CASCADE)
value = models.IntegerField()
class modelC(models.model):
model_A = models.ForeignKey('modelA', on_delete=models.CASCADE)
value = models.IntegerField()
Как я могу аннотировать запрос, чтобы получить что-то вроде этого :
q = modelA.objects.all().annotate(value= # IF THERE IS modelC exist with related modelA THEN modelC.value ELSE modelB.value #)
modelA может иметь несколько объектов modelB и modelC, но поскольку вы спрашиваете о существовании любой из моделей, я предположу, что может быть только одна из них, и возьму только первое значение. Сначала нужно аннотировать связанные значения с помощью Subquery
, а затем оценить value
с помощью sql switch-case:
from django.db.models import Case, When, Subquery, OuterRef, IntegerField
modelc_objects = modelC.objects.filter(model_A_id=OuterRef('pk'))
modelb_objects = modelB.objects.filter(model_A_id=OuterRef('pk'))
q = modelA.objects.all().annotate(
c_value=Subquery(modelc_objects.values('value')[:1]),
b_value=Subquery(modelb_objects.values('value')[:1]),
value=Case(
When(c_value__isnull=False, then=F('c_value')),
When(b_value__isnull=False, then=F('b_value')),
default=F('c_value'),
output_field=IntegerField()
)
)
Аннотируйте запрос значением из каждой связанной модели, я использовал Max
здесь, чтобы получить наибольшее значение из каждого отношения, поскольку неясно, как вы обрабатываете несколько связанных строк одной и той же модели. Затем используйте функцию базы данных Coalesce для получения первого ненулевого значения из этих предыдущих аннотаций
modelA.objects.annotate(
max_b=Max('modelb__value'),
max_c=Max('modelc__value')
).annotate(
value=Coalesce('max_c', 'max_b')
)