Django:做复杂注释和聚合的问题

标签 django django-models django-aggregation django-annotate

这是模型:

class Purchase(models.Model):
    date           = models.DateField(default=datetime.date.today,blank=False, null=True)
    total_purchase = models.DecimalField(max_digits=10,decimal_places=2,blank=True, null=True)

我想在特定日期范围内对“total_purchase”进行一个月的明智计算,如果一个月内没有购买,则总购买量应该是上个月的购买值(value)
如果在两个月内有购买,那么总购买将增加这两个......

示例:

假设用户给定的日期范围是从四月到十一月。

如果在四月份购买了 2800 美元,八月份购买了 5000 美元,十月份购买了 6000 美元。

然后输出将是这样的:
April      2800
May        2800
June       2800
July       2800
August     7800  #(2800 + 5000)
September  7800
October    13800 #(7800 + 6000)
November   13800

知道如何在 Django 查询中执行此操作吗?

谢谢

根据Raydel Miranda先生的回答。我做了以下
import calendar
import collections
import dateutil

start_date = datetime.date(2018, 4, 1)
end_date = datetime.date(2019, 3, 31)

results = collections.OrderedDict()

result = Purchase.objects.filter(date__gte=start_date, date__lt=end_date).annotate(real_total = Case(When(Total_Purchase__isnull=True, then=0),default=F('tal_Purchase')))

date_cursor = start_date

while date_cursor < end_date:
    month_partial_total = result.filter(date__month=date_cursor.month).agggate(partial_total=Sum('real_total'))['partial_total']

    results[date_cursor.month] = month_partial_total

    if month_partial_total == None:
            month_partial_total = int(0)
    else:
            month_partial_total = month_partial_total

    date_cursor += dateutil.relativedelta.relativedelta(months=1)

    return results

但是现在输出是这样的(来自上面的例子):
April      2800
May        0
June       0
July       0
August     5000
September  0
October    6000
November   0

有谁知道如何在几个月之间添加...
我想做类似的事情
e = month_partial_total + month_partial_total.next

我想添加每个month_partial_total的下一个迭代值。我认为这将解决我的问题..

知道如何在 Django 中执行此操作吗?

谢谢

最佳答案

我在你的问题中注意到了两件事:

  • 结果按月排序。
  • 总购买可以是blanknull .

  • 基于这些,我将提出这种方法:

    您可以获得给定月份的总数,您只需要处理 total_pushase 的情况。为空(作为旁注,拥有 Purchase 的实例没有任何意义,其中 total_purchase 为空,至少它必须为 0)。

    阅读 Django Conditional expressions了解更多 WhenCase .
    # Annotate the filtered objects with the correct value (null) is equivalent
    # to 0 for this requirement.
    
    result = Purchase.objects.filter(date__gte=start_date, date__lt=end_date).annotate(
        real_total = Case(
            When(total_purchase__isnull=True, then=0),
            default=F('total_purchase')
        )
    )
    
    # Then if you want to know the total for a specific month, use Sum.
    month_partial_total = result.filter(
        date__month=selected_month
    ).aggregate(
        partial_total=Sum('real_total')
    )['partial_total']
    

    您可以在函数中使用它来实现您想要的结果:
    import calendar
    import collections
    import dateutil
    
    def totals(start_date, end_date):
        """
        start_date and end_date are datetime.date objects.
        """
    
        results = collections.OrderedDict()  # Remember order things are added.
    
        result = Purchase.objects.filter(date__gte=start_date, date__lt=end_date).annotate(
            real_total = Case(
                When(total_purchase__isnull=True, then=0),
                default=F('total_purchase')
            )
        )
    
        date_cursor = start_date
        month_partial_total = 0
        while date_cursor < end_date:
            # The while statement implicitly orders results (it goes from start to end).
            month_partial_total += result.filter(date__month=date_cursor.month).aggregate(
                partial_total=Sum('real_total')
            )['partial_total']
    
    
            results[date_cursor.month] = month_partial_total
    
            # Uncomment following line if you want result contains the month names
            # instead the month's integer values.
            # result[calendar.month_name[month_number]] = month_partial_total
    
            date_cursor += dateutil.relativedelta.relativedelta(months=1)
    
        return results
    

    由于 Django 1.11 或许可以解决这个问题 SubQueries ,但我从未将其用于同一模型的子查询。

    关于Django:做复杂注释和聚合的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54142168/

    相关文章:

    python - django-graphene 更改列名称弃用

    json - 类型错误 : <object> is not JSON serializable

    python - Django 模型 : Get elements considering their presence as a foreign key in another table

    python - 如何返回用户名而不是 ID

    python - Django 测试失败,显示 'django.db.utils.ProgrammingError: relation "django_content_type“不存在”

    django 模型从外键关系求和字段

    django - 测试 IntegrityError UNIQUE 约束失败

    django - 使用日期时间字段按天对 Django 模型条目进行分组

    python - Django 相当于 COUNT 和 GROUP BY

    Django- Group by 和 Count by unique 在一起