【问题标题】:Django Query month wise with last 6 month过去 6 个月的 Django 查询月份明智
【发布时间】:2020-10-01 16:15:19
【问题描述】:

我正在尝试查询,该组是最近 6 个月的订单。

这是我的模型:

class Order(models.Model):
    created_on = models.DateTimeField(_("Created On"), auto_now_add=True)

这是我解析月份的方法:

from django.db.models import Func
class Month(Func):
    """
        Method to extract month
    """
    function = 'EXTRACT'
    template = '%(function)s(MONTH from %(expressions)s)'
    output_field = models.IntegerField()

这是我的查询:

        current_date = date.today()
        months_ago = 6
        six_month_previous_date = current_date - timedelta(days=(months_ago * 365 / 12))

        order = Order.objects.filter(
            created_on__gte=six_month_previous_date,
        ).annotate(
            month=Month('created_on')
        ).values(
            'month'
        ).annotate(
            count=Count('id')
        ).values(
            'month',
            'count'
        ).order_by(
            'month'
        )

在我的数据库order table 中,只有一个条目: 所以它正在返回

[{'month': 10, 'count': 1}]

但我不想要这样,我想要最近6个月的,如果一个月内没有销售,应该返回count: 0

像下面这样:

       [
            {'month': 10, 'count': 1},
            {'month': 9, 'count': 0}
            {'month': 8, 'count': 0}
            {'month': 7, 'count': 0}
            {'month': 6, 'count': 0}
            {'month': 5, 'count': 0}
        ]

【问题讨论】:

  • 数据库在封闭世界假设下工作,因此它不会插入带有0 的行。但是,您可以对列表进行后处理。请注意,Django 已经具有一个ExtractMonth 函数。

标签: django django-models django-orm


【解决方案1】:

数据库在封闭世界假设下工作,因此它不会插入带有0 的行。但是,您可以对列表进行后处理

from django.utils.timezone import now

order = Order.objects.filter(
    created_on__gte=six_month_previous_date,
).values(
    month=Month('created_on')
).annotate(
    count=Count('id')
).order_by('month')

order = {r['month']: r['count'] for r in order}

month = now().month
result = [
    {'month': (m % 12)+1, 'count': order.get((m % 12) + 1, 0)}
    for m in range(month-1, month-8, -1)
]

请注意,Django 已经拥有一个ExtractMonth function [Django-doc]

【讨论】:

  • 我不想运行 for 循环,你有什么替代方案来代替 for 循环吗?
  • @howrecepes:好吧,严格来说你已经正在运行for循环,因为Django内部有循环机制来读取数据库的结果。此外,这在 O(n) 中运行,因此在六个月的情况下只有六次迭代。您当然可以在六个指令中“展开”这些指令,这可能需要更多时间。此外,这些严格来说不是for 循环,而是列表和字典压缩。
猜你喜欢
  • 1970-01-01
  • 2019-04-09
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
  • 2020-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多