使用Django ORM,可以做类似于queryset.objects.annotate(Count('queryset_objects', gte=VALUE))
的事情。明白我的意思吗?
下面是一个快速示例,用于说明可能的答案:
在Django网站中,内容创建者提交文章,普通用户查看(即阅读)上述文章。文章可以发布(即供所有人阅读),也可以以草稿模式发布。描述这些要求的模型有:
class Article(models.Model):
author = models.ForeignKey(User)
published = models.BooleanField(default=False)
class Readership(models.Model):
reader = models.ForeignKey(User)
which_article = models.ForeignKey(Article)
what_time = models.DateTimeField(auto_now_add=True)
我的问题是:如何获取过去30分钟内按独特读者群排序的所有已发表文章?一、 我想计算一下在过去的半个小时里,每一篇发表的文章有多少不同的(独特的)视图,然后根据这些不同的视图生成一个文章列表。
我试过:
date = datetime.now()-timedelta(minutes=30)
articles = Article.objects.filter(published=True).extra(select = {
"views" : """
SELECT COUNT(*)
FROM myapp_readership
JOIN myapp_article on myapp_readership.which_article_id = myapp_article.id
WHERE myapp_readership.reader_id = myapp_user.id
AND myapp_readership.what_time > %s """ % date,
}).order_by("-views")
这引发了错误:语法错误在“01”或附近(其中“01”是extra中的datetime对象)。没什么好说的。
对于django>;=1.8
使用Conditional Aggregation:
说明: 通过文章的常规查询将使用
numviews
字段进行注释。该字段将被构造为CASE/WHEN表达式,由Count包装,对于readership匹配条件返回1,对于readership not matching条件返回NULL
。Count将忽略nulls和Count-only值。对于最近没有查看过的文章,您将得到0,您可以使用该
numviews
字段进行排序和筛选。PostgreSQL的查询将是:
如果我们只想跟踪唯一的查询,我们可以在
Count
中添加distinction,并使我们的When
子句返回值,我们希望distinct on。这将产生:
对于django<;1.8和PostgreSQL
您可以使用
raw
来执行由django的较新版本创建的SQL语句。显然,如果不使用raw
(即使使用extra
注入必需的JOIN
子句,也没有简单且优化的方法来查询该数据。对于django>;=2.0,可以在聚合函数中使用Conditional aggregation with a ^{} argument :
相关问题 更多 >
编程相关推荐