2

我已经在这里潜伏和学习了一段时间。现在我有一个问题,不知何故我看不到一个简单的解决方案。为了学习 django,我正在构建一个基本上跟踪预订项目的应用程序。我想做的是显示在选定的年份每个月有多少天预订了一件物品。

我有以下型号:

Asset(Model)

BookedAsset(Model):
 asset = models.ForeignKey(Asset)
 startdate = models.DateField()
 enddate = models.DateField()

所以有以下条目:

asset 1, 2010-02-11, 2010-02-13
asset 2, 2010-03-12, 2010-03-14
asset 1, 2010-04-30, 2010-05-01

我想退回以下内容:

asset 1    asset 2
-------    -------
Jan = 0    Jan = 0
Feb = 2    Feb = 0
Mar = 0    Mar = 2
Apr = 1    Apr = 0
May = 1    May = 0
Jun = 0    Jun = 0
Jul = 0    Jul = 0
Aug = 0    Aug = 0
Sep = 0    Sep = 0
Oct = 0    Oct = 0
Nov = 0    Nov = 0
Dec = 0    Dec = 0

我知道我需要首先获取日期范围内的天数(并跟踪它们是否超出当前月份并进入下个月),然后对天数进行汇总。我只是坚持如何在 Django 中优雅地做到这一点。

非常感谢任何帮助(或正确方向的提示)。

4

4 回答 4

0

我想不出用你拥有的模型结构来做这件事的方法。

这是一个相当复杂的要求,但是您解决它可能需要相当多的自定义 SQL。我认为作为一个开始,尽管您可能需要考虑更改您的结构,以便您有一张BookedAssetDay桌子,它分别代表预订的每一天。

class BookedAsset(models.Model):
    asset = models.ForeignKey(Asset)
    day = models.DateField()

然后查询看起来像:

BookedAsset.objects.extra(
    select={'month': 'MONTH(day)'}
).values('asset', 'month').annotate(Count('bookedasset__month'))
于 2010-05-23T15:53:30.340 回答
0

最后,我使用自定义查询作为我的问题的解决方案:

cursor = connection.cursor()
cursor.execute("""select to_char(allmonths.yeardate::date, 'YYYY/MM/DD') as monthdate,
                    COUNT("day") as bookings
                    from (
                    select distinct date_trunc('month', (date %s - offs)) as yeardate 
                    from generate_series(0,365,28) as offs
                    ) as allmonths
                    left join bookings_bookedassetday 
                    on EXTRACT(MONTH from "day")=EXTRACT(MONTH from yeardate) 
                    and asset_id=%s and EXTRACT(YEAR from "day") = %s
                    group by allmonths.yeardate
                    order by allmonths.yeardate asc""", [year+'-12-31', id, year])

query = cursor.fetchall()

也许这不是最 django-ist 的做法,但我发现它比用纯 django 搞清楚要容易得多:|

如果其他人有更好的选择,我会全神贯注:)

于 2010-05-30T17:12:54.643 回答
0

我不会选择上面的任何一个答案(即使我喜欢打出一些自定义 SQL,但我至少 5 年没有这样做了)并且你的模型足够简单,可以在关系范式中使用。

您正在寻找的答案是 django 聚合功能中的 annotate() 函数: http ://docs.djangoproject.com/en/dev/topics/db/aggregation/ 您只需要知道如何获取日期的月份,查询集文档中对此进行了说明:http: //docs.djangoproject.com/en/dev/ref/models/querysets/#month

为一项资产获取它的粗略示例:

BookedAsset.objects.filter(asset=asset).annotate(month_count=Count('startdate__month')).order_by('startdate__month')

(显然是错误的,但我无法重新创建你的结构来给你准确正确的陈述,摆弄一下并阅读文档)

即使在同一文档中使用连接语法,您也可以一次性处理所有资产。

于 2010-07-24T14:30:20.727 回答
0

还有另一种解决方案是通过数据库视图并使用元类选项 managed = False 将该视图映射到 django 模型

详细解释在这里:http ://anthony-tresontani.github.com/Django/2012/09/12/wka-django-orm-limitations/

于 2012-09-21T05:34:58.867 回答