Django过滤器与排除

Posted

技术标签:

【中文标题】Django过滤器与排除【英文标题】:Django filter vs exclude 【发布时间】:2011-01-26 05:09:06 【问题描述】:

django 中的 filter 和 exclude 有区别吗?如果我有

self.get_query_set().filter(modelField=x)

并且我想添加另一个条件,以下两行代码之间是否存在有意义的区别?

self.get_query_set().filter(user__isnull=False, modelField=x)

self.get_query_set().filter(modelField=x).exclude(user__isnull=True)

被认为是一种更好的做法还是它们在功能和性能上都相同?

【问题讨论】:

【参考方案1】:

两者都被懒惰地评估,所以我希望它们表现相同。 SQL 可能不同,但没有真正的区别。

【讨论】:

谢谢。所以这只是个人喜好的问题吗?我只是想确保我不会做一些莫名其妙的愚蠢的事情。 @Enrico:不是真的,这取决于你想要什么。看我的回答。在这种情况下,性能并不重要,它们是用于不同目的的两种方法。对于 SQL 生成,文档中提到了 .exclude()多个参数在底层 SQL 语句中通过 AND 连接,整个内容包含在 NOT() 中。 @Felix。谢谢。我想我的主要问题 - 我本可以更清楚地传达的是关于 django 和最终 SQL 的性能。从您的后续评论中,听起来一个可能比另一个执行得更好,但主要基于生成的 SQL。但是,将第二个语句更改为 .exclude(user__isnull=True).filter(modelField=x) 将使这两个语句或多或少再次相等。【参考方案2】:

通常排除与过滤相反。在这种情况下,两个示例的工作方式相同。

这里:

self.get_query_set().filter(user__isnull=False, modelField=x)

您选择字段 user 不为 null 且 modelField 具有值 x 的条目

在这种情况下:

self.get_query_set().filter(modelField=x).exclude(user__isnull=True)

首先选择 modelField 的值为 x 的条目(用户为 null 且用户不为 null),然后排除字段 user 为 null 的条目。

我认为在这种情况下最好使用第一个选项,它看起来更干净。但两者的工作方式相同。

【讨论】:

@angrysmit 你有这个声明的参考吗?【参考方案3】:

这取决于您想要实现的目标。使用布尔值很容易在.exclude().filter() 之间切换,但是例如如果您想获取除 3 月的文章之外的所有文章?您可以将查询编写为

Posts.objects.exclude(date__month=3)

使用.filter() 会是(但我不确定这是否真的有效):

Posts.objects.filter(date__month__in=[1,2,4,5,6,7,8,9,10,11,12])

否则您将不得不使用Q 对象。

正如函数名称所暗示的,.exclude() 用于从结果集中排除数据集。对于布尔值,您可以轻松地将其反转并改用.filter(),但对于其他值,这可能会更加棘手。

【讨论】:

以上是关于Django过滤器与排除的主要内容,如果未能解决你的问题,请参考以下文章

Django REST Framework 中的否定或排除过滤器

在 django 中,我如何过滤或排除多个东西?

使用跨越关系的字段查找在 django 模型上进行链式过滤和排除

如何从我的带注释的 Django 查询中过滤/排除非活动评论?

django-mptt 过滤而不破坏树

Django 查询集过滤器文件字段不为空