问题
I want to write a Django query to give me the average across all rows in my table. My model looks like
class StatByDow(models.Model):
total_score = models.DecimalField(default=0, max_digits=12, decimal_places=2)
num_articles = models.IntegerField(default=0)
day_of_week = IntegerField(
null=True,
validators=[
MaxValueValidator(6),
MinValueValidator(0)
]
)
and I attempt to calculate the average like this
everything_avg = StatByDow.objects.all().aggregate(Avg(Func(F('total_score') / F('num_articles'))))
but this results in the error
File "/Users/davea/Documents/workspace/mainsite_project/venv/lib/python3.7/site-packages/django/db/models/query.py", line 362, in aggregate
raise TypeError("Complex aggregates require an alias")
TypeError: Complex aggregates require an alias
What's the right way to calculate the average?
回答1:
You don't need Func
for the division, but you need to reconcile the two different field types. Use an ExpressionWrapper around Avg
:
from django.db.models import ExpressionWrapper
everything_avg = (StatByDow.objects
.aggregate(avg=ExpressionWrapper(
Avg(F('total_score') / F('num_articles')),
DecimalField()
))
)
You could also use a Cast
from integer to decimal (not with PostgreSQL, which objects to Django's syntax ::numeric(NONE, NONE)
) or an ExpressionWrapper
around the division, but just one ExpressionWrapper
at the end is the quickest solution as it happens once at the end.
回答2:
you need to pass a name of an alias (obviously by the error text) for aggregate function. the query should be something like this:
everything_avg = StatByDow.objects.all().aggregate(avg_f=Avg(Func(F('total_score') / F('num_articles'))))
来源:https://stackoverflow.com/questions/55458958/how-to-aggregate-the-average-of-a-calculation-based-on-two-columns