【问题标题】:Django annotate price per monthDjango 每月注释价格
【发布时间】:2017-02-13 08:03:05
【问题描述】:

我想在 SO 上将此参考我的另一个 Question,所以我试图显示每月价格并制作一个包含 12 个月的表格,一行包含每月项目总收入,所以我已经成功计算我的价格使用

context["price_aux"] = Project.objects.annotate().aggregate(Sum("price_aux"))

我可以在表格中显示我的数据并为此制作一行总计,但正如您从我之前的问题中看到的那样,我想每月对此进行注释并制作一个表格,然后显示当月的总计,但我真的很难理解如何从我的数据库中提取它,那么在django==1.8+ 中执行此操作的正确方法是什么,我看到在最近的版本中他们添加了Extract,但我不能在 1.8 中使用它,第二件事是django extra 他们在这里说Use this method as a last resort,所以你能解释一下我怎样才能做到这一点。

【问题讨论】:

  • 为什么不使用包含两列的表格,一列用于月份,另一列用于价格。然后你可以简单地按月选择价格。
  • 我正在使用类似的东西,但是我很难从 db 中提取 moth,可以举一个小例子吗?
  • 假设你的模型被称为Prices 并且有两个字段monthprice 然后你做ppm = Prices.objects.filter(month=1)[0]ppm.price然后给你实际价格。
  • 好的,问题是我有 created 字段,即 DateTimeField,而我所做的是我有 TypeError: expected string to buffer,我可以使用 created__month,但是我有列表index out of range

标签: python mysql django


【解决方案1】:

我的建议是在模型中添加一个字段,因为在 .values_list 中无法使用 __month。 Values_list 可用于在注释之前对查询进行分组。

字段可能类似于。

year_month = models.CharField(index=True)

您可以覆盖模型上的保存方法并执行类似的操作

def save(self, *args, **kwargs)
    # Not sure if auto_add_now already set the value, could use timezone.now()
    if not self.id:  # thus not saved yet
        self.year_month = self.created_at.strftime("%Y%m")
    super(Model, self).save(*args, **kwargs)

现在可以注释您的价格了。

Project.objects.values_list('year_month').annotate(price_sum=Sum("price_aux"))

如果您需要更多信息,我相信您可以扩展 values_list。

Project.objects.values_list('year_month').annotate(price_sum=Sum("price_aux")) \
    .values_list('name', 'year_month', 'price_sum')

当然可以不添加字段。假设你想要过去的一年。

import datetime
from django.utils import timezone

def my_list_view(request):
    end = timezone.now()
    # note, could do some weird stuff in years with 366 days
    begin = (end - datetime.timedelta(days=365)).replace(day=1)  

    container = {}
    while begin < end:
        container[begin.strftime("%Y%m")] = 0
        begin = (begin + datetime.timedelta(weeks=5).replace(day=1)

    for project in Project.objects.iterator():
        container[project.created_at.strftime("%Y%m")] += price

    # Now you can render your template

【讨论】:

  • 好的,是否值得通过 hand 进行此计算,在我的 ListView 中使用 iterator() 而不是在 models.py 中添加新字段,不过这很有趣我会试试的,我只是想知道这种更多的python计算每月价格的方法
  • 我在这个模板中使用了通用的ListView,所以我可以做一个mixin 并做这个计算
  • 从未使用过ListView,也从未听说过 Django 中的 mixin,但很高兴我的回答对您有所帮助。
【解决方案2】:

假设您的模型名为Prices,并且有两个字段dateprice,其中date 是一个日期时间字段。然后您可以使用date__month(注意双下划线)作为查询方法的关键字参数(请参阅field lookups 的文档)。

您可以通过以下方式按月检索价格

Prices.objects.get(date__month=1).price

【讨论】:

    猜你喜欢
    • 2021-06-26
    • 2016-09-20
    • 2011-04-02
    • 1970-01-01
    • 1970-01-01
    • 2020-01-19
    • 1970-01-01
    • 1970-01-01
    • 2014-03-17
    相关资源
    最近更新 更多