Django Subquery Sum без результатов возвращает None вместо 0
У меня есть подзапрос Django, который возвращает сумму. Если подзапрос находит хотя бы один результат, он работает нормально. Но если подзапрос не находит ни одной записи, он возвращает None, что приводит к тому, что любые другие вычисления, использующие этот результат (я использую его позже в моем запросе в F-выражении), также приводят к None.
Я пытаюсь суммировать все не нулевые значения 'consumed' - иногда они все нулевые и поэтому нет строк, по которым можно суммировать. Я бы хотел, чтобы в результате получался 0, а не None
...
annotate(tapx=Subquery(InvTrx.objects.filter(job=OuterRef('job')).\
filter(consumed__isnull=False).\
filter(inventory__inv_type='APX').\
values('job__job').\
annotate(tot_cons=Sum('consumed', default=0)).\
values('tot_cons')
)).\
...
Я пробовал Coalesce с и без Value(0)
annotate(tot_cons=Coalesce(Sum('consumed', default=0)), 0).\
annotate(tot_cons=Coalesce(Sum('consumed', default=0)), Value(0)).\
значение tapx (которое я повторно использую в F-выражениях в другой части запроса) = None, если не возвращается ни одного ряда. Если возвращается хотя бы одна строка, это работает нормально. Если не возвращается ни одной строки, я бы хотел, чтобы значение tapx было 0, а не None, чтобы значение fg_total в следующей аннотации давало число, а не None:
annotate(fg_total=F('fg') + F('tapx'))
Делая это вне подзапроса, я использовал "or 0", чтобы заставить значение равняться 0, если результат None - есть ли способ сделать это внутри подзапроса?
Я также пытался, когда я использую результат подзапроса в выражении F, использовать условие, как например:
annotate(fg_total=F('fg') + Case(When(~Exists('tapx'), then=F('tapx')),default=Value(0)))
но это приводит к ошибке - объект 'str' не имеет атрибута 'order_by' (я не уверен, что это означает в данном контексте, поскольку я нигде не использую 'order_by'?)
Я использую Django 3.0. Я застрял.
Вы должны не Coalesce
.annotate(…)
в Subquery
, а результат от Subquery
, так:
.annotate(tapx=Coalesce(
Subquery(InvTrx.objects.filter(
job=OuterRef('job'), consumed__isnull=False, inventory__inv_type='APX'
).values('job_id').annotate(tot_cons=Sum('consumed')).values('tot_cons')),
Value(0))
)