список значений в EmptyQuerySet, используемый в фильтре queryset, возвращает полный набор
недавно нашел что-то особенное в фильтре, я не могу поверить в его предполагаемое поведение.
from django.contrib.auth.models import User
print User.objects.filter(id__in=User.objects.none().values_list("id",flat=True))
print User.objects.filter(id__in=User.objects.all().values_list("id",flat=True))
Как ни странно, оба этих списка возвращают полный набор пользователей. На самом деле, кажется, довольно легко "исправить", если я оберну внутренний запрос в функцию списка, например
User.objects.filter(id__in=list(User.objects.none().values_list("id")))
затем он возвращает то, что я ожидал (пустой список).
Кажется мне ошибкой, или я что-то пропустил?
Стив
1 ответов
вот запросы как:
пользователей.объекты.фильтр (id__in=пользователь.объекты.никто.)(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
пользователей.объекты.фильтр (id__in=пользователь.объекты.все.)(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()
, User.objects.filter(id__in=[])
и User.objects.filter(id__in=User.objects.none()
. Во всех трех из них обстоятельства, Django короткое замыкание запроса. Другими словами, он даже не выдает запрос в базу данных, поскольку заранее определяет, что результатов не будет. Мое лучшее предположение здесь, что добавление values_list
до конца побеждает логику короткого замыкания, позволяя отправлять фактический запрос, и это на самом деле values_list
что определяет запрос, который должен быть отправлен. Что в обоих случаях действительно одно и то же, если подумать. В любом случае вы хотите выбрать только id
на Ан нефильтрованное объект QuerySet.
я подчеркнул эту часть, потому что я уверен, что вы прыгаете вверх и вниз, говоря, но none
должен возвращать пустой queryset. Верно, но это происходит благодаря автоматическому возврату EmptyQuerySet
и вообще никогда не запрашивал базу данных. Он не добавляет никаких фильтров в запрос.
является ли это ошибкой или нет, спорно. Я более склонен называть это крайним случаем, который, скорее всего, не может быть "исправлен". Это функция того, как все переплетающиеся части объединяются в этом одном сценарии.