获取切片后过滤Django查询集

时间:2016-05-12 16:29:47

标签: django django-models django-queryset

在我维护的django论坛中,我会禁止那些辱骂的用户4天。在论坛的“主页”中,我会显示每个人的评论,但不包括遭到地狱禁止的人的评论。它是这样的:

    def get_queryset(self):
        if self.request.user_banned: #if user is hell-banned
            return Link.objects.order_by('-id')[:120]
        else: #if user is not hell-banned
            global condemned
            queryset = Link.objects.order_by('-id').exclude(submitter_id__in=condemned)[:120]
            return queryset

以上是get_queryset的{​​{1}}方法。请注意,如果地狱禁止的用户不能告诉他们的评论被排除在网站之外(地狱禁令)。 ListView是一个包含地狱禁止用户主键的列表。

现在我想首先通过切片来优化上述内容,然后将被禁止的人排除在外。我试图通过以下方式做到这一点:

condemned

这不幸地给了我错误:

  

切片拍摄后无法过滤查询。

我有哪些替代品?需要我能找到的最有效的解决方案,因为性能是关键。我在Django< 1.8。提前致谢。

1 个答案:

答案 0 :(得分:0)

首先,Django不允许您在切片后进行过滤,因为在基础SQL中,您无法轻松limit结果,然后使用where进行过滤。

进行过滤然后切片可能不是问题。注意querysets are lazy,所以Django只会从db中获取120个对象。

您需要进行一些基准测试,以确定排除是否真的让您失望。您可以测试exclude和切片的查询是否明显慢于仅使用切片的查询。

如果您发现排除速度很慢,可以在Python中过滤

comments = [c for c in comments if c.submitter_id not in condemned]. 

请注意,您最终可能会收到少于120条评论。

另一个选项是向condemned模型添加Submitter标记,然后将查询更改为.exclude(submitter__condemned=True)。这可能比当前.exclude(submitter_id__in=condemned)更快。

您还应检查您的数据库是否包含submitter_id字段的索引。因为它是外键,所以可能会这样做。

相关问题