Я использую агрегатное выражение запроса Django для суммирования некоторых значений. Конечное значение - это выражение деления, которое иногда может содержать ноль в качестве знаменателя. Мне нужен способ уйти, если это так, чтобы он просто возвращал 0.
Я пробовал следующее, так как использовал что-то похожее на мои выражения аннотации:
from django.db.models import Sum, F, FloatField, Case, When
def for_period(self, start_date, end_date):
return self.model.objects.filter(
date__range=(start_date, end_date)
).aggregate(
sales=Sum(F("value")),
purchase_cogs=Sum(F('purchase_cogs')),
direct_cogs=Sum(F("direct_cogs")),
profit=Sum(F('profit'))
).aggregate(
margin=Case(
When(sales=0, then=0),
default=(Sum(F('profit')) / Sum(F('value')))*100
)
)
Я пробовал следующее, так как использовал что-то похожее на мои выражения аннотации:…
объект 'dict' не имеет атрибута 'aggregate'
Как правильно с этим справиться?
3 ответа
Очевидно, это не сработает; потому что aggregate
возвращает словарь, а не QuerySet (см. docs), поэтому вы не можете связать два вызова aggregate
вместе.
Я думаю, что использование annotate
решит вашу проблему . annotate
почти идентичен aggregate
, за исключением того, что он возвращает QuerySet с результатами, сохраненными как атрибуты, а не возвращает словарь. В результате вы можете связать вызовы annotate
или даже позвонить annotate
, затем aggregate
.
Так что я считаю что-то вроде:
return self.model.objects.filter(
date__range=(start_date, end_date)
).annotate( # call `annotate`
sales=Sum(F("value")),
purchase_cogs=Sum(F('purchase_cogs')),
direct_cogs=Sum(F("direct_cogs")),
profit=Sum(F('profit'))
).aggregate( # then `aggregate`
margin=Case(
When(sales=0, then=0),
default=(Sum(F('profit')) / Sum(F('value')))*100
)
)
Должно сработать.
Надеюсь это поможет.
Вы не можете объединить такие агрегированные утверждения в цепочку. В документах говорится:
aggregate () - это терминальное предложение для QuerySet, которое при вызове возвращает словарь пар имя-значение.
Aggregate () - это терминальное предложение для QuerySet, которое при вызове возвращает словарь пар имя-значение.…
В отличие от aggregate (), annotate () не является терминальным предложением. Результатом предложения annotate () является QuerySet.
В отличие от aggregate (), annotate () не является терминальным предложением. Результатом предложения annotate () является QuerySet.…
Я заставил его работать (в Django 2.0) с помощью:
from django.db.models import Case, F, FloatField, Sum, When
aggr_results = models.Result.objects.aggregate(
at_total_units=Sum(F("total_units")),
ag_pct_units_sold=Case(
When(at_total_units=0, then=0),
default=Sum("sold_units") / (1.0 * Sum("total_units")) * 100,
output_field=FloatField(),
),
)
Похожие вопросы
Связанные вопросы
Новые вопросы
django
Django - это серверная платформа веб-приложений с открытым исходным кодом, написанная на Python. Он разработан для сокращения усилий, необходимых для создания сложных веб-сайтов и веб-приложений, управляемых данными, с особым упором на меньшее количество кода, отсутствие избыточности и более явное, чем неявное.