Django queryset额外查询中的语法错误

时间:2015-11-19 09:23:31

标签: python sql django django-queryset

以下包含语法错误:

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"是额外的日期时间对象)。继续下去并不多。有人可以指出发生了什么吗?

背景:与上述代码相关的模型是:

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分钟内所经历的独特读者排序。即计算每个已发表文章在过去半小时内获得的不同(唯一)视图的数量,然后生成按这些不同视图排序的文章列表。我的代码缺少处理要求的 ' 部分 - 我不知道如何在此处完成此操作。

1 个答案:

答案 0 :(得分:3)

您永远不应该在SQL查询中使用字符串替换,无论这是否是extra调用的一部分。您之前发现了一个原因 - 因为没有正确引用值 - 但更重要的原因是它让您对SQL注入开放。

相反,请使用db api为您提供的功能:在这种情况下,请使用select_params

.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 """
    },
    select_params=(date,),
)

另见备注in the docs;不推荐使用extra方法,并且可以使用其他ORM方法表达查询。