如何获取Django查询,使其仅返回平均值和另一列?

时间:2019-04-10 17:00:07

标签: python django python-3.x aggregate average

我正在使用Django和Python 3.7。我有这些模型...

class Article(models.Model):
    website = models.ForeignKey(Website, on_delete=models.CASCADE, related_name='articlesite')
    title = models.TextField(default='', null=False)
    path = models.TextField(default='', null=False)
    url = models.TextField(default='', null=False)
    created_on = models.DateTimeField(db_index=True, default=datetime.now)


class ArticleStat(models.Model):
    objects = ArticleStatManager()
    article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='articlestats')
    elapsed_time_in_seconds = models.IntegerField(default=0, null=False)
    hits = models.FloatField(default=0, null=False)

我想编写一个Django查询,该查询返回两列数据-elapsed_time_in_seconds(来自上面的ArticleStat模型)和该特定时间间隔的平均点击数。混合还有其他一些约束。我不知道该怎么做。我尝试了以下

qset = ArticleStat.objects.annotate(avg_score=Avg(F("hits")),
                                    hour=(Func(
                                            Func(
                                                F("article__created_on"), function='HOUR FROM'),
                                            function='EXTRACT'))).filter(
    article__website=website,
    hour=hour)

但是会导致错误“ TypeError:预期的字符串或类似字节的对象”。我对如何指定SQL语句的“ GROUP BY”部分感到困惑,然后对如何返回所需的两列数据感到困惑,因为我认为以上内容仅返回ArticleStat对象,而不会不要把我的平均数包括在内。

1 个答案:

答案 0 :(得分:0)

您需要在hour注释上设置一个输出字段,否则Django不知道您已将原始日期类型(created_on)转换为数字类型(hour) ,并且希望传递一个日期字符串(或一个日期对象,但令人困惑的是,它没有说)。如果您将日期hour传递到filter(),则会看到TypeError消失了(但您将从数据库中获得了ProgrammingError)。

因此,假设您将小时提取为整数,那么如何使用IntegerField

from django.db.models import IntegerField

qset = ArticleStat.objects.annotate(
    avg_score=Avg(F("hits")),
    hour=(Func(
            Func(F("article__created_on"), function='HOUR FROM'),
            function='EXTRACT',
            output_field=IntegerField()
    ))
)