以下是为两者生成的查询:
User.objects.filter(id__in=User.objects.none().values_list("id",flat=True))
SELECT "auth_user"."id",
"auth_user"."username",
"auth_user"."first_name",
"auth_user"."last_name",
"auth_user"."email",
"auth_user"."password",
"auth_user"."is_staff",
"auth_user"."is_active",
"auth_user"."is_superuser",
"auth_user"."last_login",
"auth_user"."date_joined"
FROM "auth_user"
WHERE "auth_user"."id" IN
(SELECT U0."id"
FROM "auth_user" U0) LIMIT 21
User.objects.filter(id__in=User.objects.all().values_list("id",flat=True))
SELECT "auth_user"."id",
"auth_user"."username",
"auth_user"."first_name",
"auth_user"."last_name",
"auth_user"."email",
"auth_user"."password",
"auth_user"."is_staff",
"auth_user"."is_active",
"auth_user"."is_superuser",
"auth_user"."last_login",
"auth_user"."date_joined"
FROM "auth_user"
WHERE "auth_user"."id" IN
(SELECT U0."id"
FROM "auth_user" U0) LIMIT 21
注意到什么了吗?它们是完全相同的查询。同样有趣的是,如果您尝试诸如和之类User.objects.none()
的东西会发生什么。在所有这三种情况下,Django 都会使查询短路。换句话说,它甚至不会向数据库发出查询,因为它事先确定不会有任何结果。我在这里最好的猜测是,添加到最后会破坏短路逻辑,允许发送实际查询,并且它实际上决定了应该发送的查询。当您考虑时,这两种情况实际上是相同的。无论哪种方式,您都只想在未过滤的查询集上进行选择。User.objects.filter(id__in=[])
User.objects.filter(id__in=User.objects.none()
values_list
values_list
id
我强调了那部分,因为我确定您现在正在上下跳跃,但none
应该返回一个空的查询集。没错,但它是通过自动返回一个EmptyQuerySet
并且根本不实际查询数据库来做到这一点的。它不会向查询添加任何过滤器。
这是否是一个错误是有争议的。我更倾向于称这是一个很可能无法真正“修复”的极端情况。这是所有交织部分在这个场景中如何组合在一起的函数。