Django每天记录总数

2024-04-29 21:39:25 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个django应用程序正在做日志记录。我的模型是这样的:

class MessageLog(models.Model):
    logtime = models.DateTimeField(auto_now_add=True)
    user = models.CharField(max_length=50)
    message = models.CharField(max_length=512)

我们要做的是获取一周中每天记录的平均消息数,这样我就可以看到哪一天是最活跃的。我已经设法编写了一个查询,该查询每天提取邮件总数,即:

for i in range(1, 8):
    MessageLog.objects.filter(logtime__week_day=i).count()

但我在计算查询中的平均值时遇到问题。我现在拥有的是:

for i in range(1, 8):
    MessageLog.objects.filter(logtime__week_day=i).annotate(num_msgs=Count('id')).aggregate(Avg('num_msgs'))

但由于某些原因,它每天返回1.0。我查看了它生成的SQL,它是:

SELECT AVG(num_msgs) FROM (
SELECT 
`myapp_messagelog`.`id` AS `id`, `myapp_messagelog`.`logtime` AS `logtime`, 
`myapp_messagelog`.`user` AS `user`, `myapp_messagelog`.`message` AS `message`, 
COUNT(`myapp_messagelog`.`id`) AS `num_msgs` 
FROM `myapp_messagelog` 
WHERE DAYOFWEEK(`myapp_messagelog`.`logtime`) = 1 
GROUP BY `myapp_messagelog`.`id` ORDER BY NULL
) subquery

我想问题可能是来自于按身份分组,但我不太确定。有人有什么想法或建议吗?提前谢谢!


Tags: idmessagemodelsas记录lengthmyappnum
3条回答

列出的查询总是给出1的原因是您没有按日期分组。基本上,您已经要求数据库获取一周中某一天的MessageLog行。对于每一行,计算它有多少id(总是1)。然后取所有这些计数的平均值,当然也是1。

通常,需要使用^{}子句在annotateaggregate部分之前对MessageLog行进行分组。但是,由于您的logtime字段是一个日期时间,而不仅仅是一个日期,所以我不确定您是否可以用Django的ORM直接表示它。您肯定可以使用extra子句来完成,如here所示。或者,如果您喜欢,可以在SQL中声明一个视图,其中包含您喜欢的聚合和平均数学量,并为它声明一个非托管模型,然后正常使用ORM。

因此,一个extra字段可以获得每一天的记录总数,但不处理聚集计算的注释的平均值。我认为这可能是从模型中充分抽象出来的,您必须使用原始SQL查询,或者至少我在一个调用中找不到任何使其工作的东西。

也就是说,您已经知道如何在问题中显示的简单查询中获取每个工作日的总记录数。

这个查询将告诉您在给定的工作日有多少不同的日期记录:

MessageLog.objects.filter(logtime__week_day=i).dates('logtime', day').count()

所以你可以用Python来计算平均值,这可能比尝试正确使用SQL要简单得多。

或者,此查询将在一个查询中获取所有工作日的原始邮件数,而不是for循环:

MessageLog.objects.extra({'weekday': "dayofweek(logtime)"}).values('weekday').annotate(Count('id'))

但是我还没有得到一个好的查询来为每个工作日提供不同日期的计数注释到那个日期querysets失去了处理注释调用的能力,并且在一个extra值上注释似乎也不起作用。

考虑到SQL表达式并没有那么难,这一点非常棘手。

queryset.extra(select={'day': 'date(logtime)'}).values('day').order_by('-day').annotate(Count('id'))

我对datetime字段做了一些类似的操作,但对额外值进行注释对我确实有效。我有一个记录模型,其中有一个日期时间字段“created_at”和一个“my_auvalue”字段,我想得到它们的平均值。

from django.db.models import Avg

qs = Record.objects.extra({'created_day':"date(created_at)"}).\
    values('created_day').\
    annotate(count=Avg('my_value'))

以上将按“创建时间”字段中日期时间值的日期分组。

相关问题 更多 >