1

在官方 Django 文档中,关于从查询集中排除的部分(https://docs.djangoproject.com/en/dev/ref/models/querysets/#exclude),有几个查询的解释:

此示例排除所有 pub_date 晚于 2005-1-3 且标题为“Hello”的条目:

Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline='Hello')

在 SQL 术语中,计算结果为:

SELECT ...
WHERE NOT (pub_date > '2005-1-3' AND headline = 'Hello')

此示例排除所有 pub_date 晚于 2005-1-3 或标题为“Hello”的条目:

Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3)).exclude(headline='Hello')

在 SQL 术语中,计算结果为:

SELECT ...
WHERE NOT pub_date > '2005-1-3'
AND NOT headline = 'Hello'

请注意,第二个示例更具限制性。

最后一个我不清楚。我看不出第一个和第二个之间有什么区别,谁能解释一下?

4

2 回答 2

2

第一个示例创建一个嵌套的子表达式,而第二个示例创建两个单独的表达式。

于 2013-02-15T12:56:04.450 回答
1

如果您的意思是“注意第二个示例更具限制性。”部分,也许更数学的方法可以帮助您:

NOT (pub_date > '2005-1-3' AND headline = 'Hello')

可以翻译成:

NOT pub_date > '2005-1-3' OR NOT headline = 'Hello'

与之相比:

NOT pub_date > '2005-1-3' AND NOT headline = 'Hello'

限制较少,因为您希望 的任一部分为OR真,即 -A OR B限制小于A AND B.

回到文档,在第一种情况下,您排除了同时符合这两个限制的人。而在第二个中,您排除了符合第一个限制的人,并排除了符合第二个限制的人,也就是说 - 您排除了符合任何一个限制的人。

@OP 的评论:假设我们有四个项目 AA、AB、BB 和 CC。如果我们说:

Item.objects.filter(name_startswith='A', name_endswith='B')

结果将是 {AB}。当然,如果我们说:

Item.objects.exclude(name_startswith='A', name_endswith='B')

结果将是 {AA, BB, CC},因为我们只想排除那些以 'A' 开头并以 'B' 结尾的人。下一个:

Item.objects.exclude(name_startswith='A')

将导致 {BB, CC}。但是,当我们链接另一个排除时:

Item.objects.exclude(name_startswith='A').exclude(name_endswith='B')

我们实际上是在说THE_RESULT_OF_THE_FIRST_EXCLUDE.exclude(name_endswith='B')。那是:

{BB, CC}.exclude(name_endswith='B')

这将返回 {CC}。不同于filter, 其中

Item.objects.filter(<condition_1>).filter(<condition_2>)

与以下结果相同:

Item.objects.filter(<condition_1>, <condition_2>)

排除是链式的。它类似于布尔运算:

NOT(A AND B) = NOT A OR NOT B NOT(A OR B) = NOT A AND NOT B

于 2013-02-15T13:17:48.340 回答