Django:计算每个用户的平均每月支出

Django: Calculate average monthly spend per user

给定一个存储用户交易的 Django 模型,我如何创建一个查询 returns 每个用户的平均每月支出?

我当前的解决方案查询所有交易,迭代结果并使用字典计算每个用户的平均值。我知道有一种更有效的方法可以使用 aggregate/annotate 来查询它,但不确定如何编写它。

我更关心可读性而不是速度,因为数据库中的事务数量相对较少并且永远不会改变。

models.py

Class Transactions(models.Model):
  id = models.AutoField(primary_key=True)
  user = models.ForeignKey('User', on_delete=models.CASCADE)
  amount = models.DecimalField(max_digits=100, decimal_places=2)
  date = models.DateField()

深夜研究这个(未经测试)。下面的代码从日期中提取年和月,然后使用 order_by() 清除顺序(可能并非在所有情况下都需要),然后按 'user'、'year' 分组, 'month' 并计算平均值,使用 Avg 函数存储在名为 'average' 的列中。

Documentation 还有其他一些很好的例子。

from django.db.models.functions import ExtractMonth, ExtractYear
from django.db.models import Avg
...

avg_by_user_by_month = Transactions.objects
                                   .annotate(month=ExtractMonth('date'),
                                             year=ExtractYear('date'),) \
                                   .order_by()\
                                   .values('user', 'year', 'month')\
                                   .annotate(average=Avg('amount'))\
                                   .values('user', 'year', 'month', 'average')
        

编辑 或者,这也可能有效:

from django.db.models import Avg, F
...

avg_by_user_by_month = Transactions.objects
                                   .annotate(month=F('date__month'),
                                             year=F('date__year'),) \
                                   .order_by()\
                                   .values('user', 'year', 'month')\
                                   .annotate(average=Avg('amount'))\
                                   .values('user', 'year', 'month', 'average')