gpt4 book ai didi

django - 每天使用 .latest() 查询集

转载 作者:行者123 更新时间:2023-12-04 04:22:01 25 4
gpt4 key购买 nike

我有一个基本模型,例如:

class Stats(models.Model):

created = models.DateTimeField(auto_now_add=True)
growth = models.IntegerField()

我每 10 分钟运行一次 celery 作业以创建一个新的 stats 对象。

使用 .latest()QuerySet给了我迄今为止最新的 Stats 对象。

但是,我想要一个包含每天一个 Stats 对象的列表。

考虑以下:
Stats(growth=100) #created 1/1/13 23:50
Stats(growth=200) #created 1/1/13 23:59
Stats(growth=111) #created 1/2/13 23:50
Stats(growth=222) #created 1/2/13 23:59
QuerySet应该返回每天的最新信息。在示例中,增长了 200 和 222。

在 SQL 中,我会为每天的最大值启动一个子查询并将其连接在一起。

由于我不想使用原始 SQL,有没有办法用 django ORM 做到这一点?

最佳答案

不幸的是,没有办法(我知道..我看起来很努力)避免使用某种原始 sql 来完成你想做的事情 (使用您当前的模型;看到最后的另一个建议) .但是您可以通过编写尽可能少的原始 sql 来最小化影响。在实践中,django 站点不需要跨不同的数据库移植。除非您打算在其他地方使用此应用程序或公开发布它,否则您应该没问题。

以下示例适用于 sqlite。您可以保留数据库类型到 date 的映射。功能,查找驱动程序的类型,并在需要时将功能替换为正确的功能。

>>> for stat in Stats.objects.all():
... print stat.created, stat.growth
...
2013-06-22 13:41:25.334262+00:00 3
2013-06-22 13:41:40.473373+00:00 3
2013-06-22 13:41:44.921247+00:00 4
2013-06-22 13:41:47.533102+00:00 5
2013-06-23 13:41:58.458250+00:00 6
2013-06-23 13:42:01.282702+00:00 3
2013-06-23 13:42:03.633236+00:00 1

>>> last_stat_per_day = Stats.objects.extra(
select={'the_date': 'date(created)' }
).values_list('the_date').annotate(max_date=Max('created'))

>>> last_stat_per_day
[(u'2013-06-22', datetime.datetime(2013, 6, 22, 13, 41, 47, 533102, tzinfo=<UTC>)), (u'2013-06-23', datetime.datetime(2013, 6, 23, 13, 42, 3, 633236, tzinfo=<UTC>))]

>>> max_dates = [item[1] for item in last_stat_per_day]
>>> max_dates
[datetime.datetime(2013, 6, 22, 13, 41, 47, 533102, tzinfo=<UTC>),
datetime.datetime(2013, 6, 23, 13, 42, 3, 633236, tzinfo=<UTC>)]

>>> stats = Stats.objects.filter(created__in=max_dates)
>>> for stat in stats:
... print stat.created, stat.growth
...
2013-06-22 13:41:47.533102+00:00 5
2013-06-23 13:42:03.633236+00:00 1

我之前在这里写过,这只是一个查询,但我撒了谎 - values_list 需要转换为仅返回后续查询的 max_date,这意味着运行该语句。虽然它只有 2 个查询,但比 N+1 函数要好得多。

非可移植位是这样的:
last_stat_per_day = Stats.objects.extra( 
select={'the_date': 'date(created)' }
).values_list('the_date').annotate(max_date=Max('created'))

使用 extra并不理想,但这里的原始 sql 很简单,并且非常适合依赖于数据库驱动程序的替换。只有 date(created)需要更换。如果愿意,您可以将其包装在自定义管理器上的方法中,然后您已成功地将这些困惑抽象到一个位置。

另一种选择是添加 DateField到您的模型,然后您根本不需要使用额外的。您只需替换 values_list调用 values_list('created_date') , 删除 extra完全,并收工。成本是显而易见的——需要更多的存储空间。至于为什么你有一个 Date 也是不直观的。和 DateTime同一模型上的字段。保持两者同步也可能会带来问题。

关于django - 每天使用 .latest() 查询集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17212997/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com