Наборы запросов Django ленивы. Это означает, что запрос попадет в базу данных только тогда, когда вы конкретно запросите результат.
Таким образом, до тех пор, пока вы не распечатаете или не используете результат запроса, вы можете выполнять дальнейшую фильтрацию без доступа к базе данных.
Как вы можете видеть ниже, ваш код выполняет только один SQL-запрос, чтобы получить только последние 10 элементов.
In[19]:import logging In[20]: l = logging.getLogger('django.db.backends')In[21]: l.setLevel(logging.DEBUG)In[22]: l.addHandler(logging.StreamHandler())In[23]:User.objects.all().order_by('-id')[:10](0.000) 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" ORDER BY "auth_user"."id" DESC LIMIT 10; args=()Out[23]:[<User: hamdi>]
Я попробовал это на mongoDB, и он говорит, что SELECT не поддерживается. Как это сделать на mongoDB?
winux
@winux Поскольку это специфично для Django, может показаться, что вам может понадобиться настроить Django для работы именно с базами данных Mongo / NoSQL. По моему опыту, это не типичная настройка для стандартной установки Django ORM.
анонимный трус
38
На самом деле, я думаю, что LIMIT 10они будут выданы базе данных, поэтому срезы будут выполняться не в Python, а в базе данных.
Обратите внимание, что это не будет работать для наборов запросов, которые также нуждаются в фильтрации, так как вы не можете фильтровать после нарезки.
Майк 'Pomax' Камерманс
2
Поэтому сначала отфильтруйте, чем нарежьте. Спасибо Давору за ссылку!
Вячес
13
Похоже, что решение в вопросе больше не работает с Django 1.7 и выдает ошибку: «Невозможно изменить порядок запроса после того, как был взят фрагмент»
Тем не менее, мне интересно, выполняется ли ограничение в срезах SQL или Python, весь возвращаемый массив результатов. Нет смысла извлекать огромные списки из памяти приложения.
В качестве дополнения и наблюдения к другим полезным ответам, стоит заметить, что на самом деле выполнение [:10]срезов вернет первые 10 элементов списка , а не последние 10 ...
Чтобы получить последние 10 вы должны сделать [-10:]вместо этого (см. Здесь ). Это поможет вам избежать использования order_by('-id')с -реверсом элементов.
Ответы:
Наборы запросов Django ленивы. Это означает, что запрос попадет в базу данных только тогда, когда вы конкретно запросите результат.
Таким образом, до тех пор, пока вы не распечатаете или не используете результат запроса, вы можете выполнять дальнейшую фильтрацию без доступа к базе данных.
Как вы можете видеть ниже, ваш код выполняет только один SQL-запрос, чтобы получить только последние 10 элементов.
источник
На самом деле, я думаю, что
LIMIT 10
они будут выданы базе данных, поэтому срезы будут выполняться не в Python, а в базе данных.См. Limiting-querysets для получения дополнительной информации.
источник
Похоже, что решение в вопросе больше не работает с Django 1.7 и выдает ошибку: «Невозможно изменить порядок запроса после того, как был взят фрагмент»
Согласно документации https://docs.djangoproject.com/en/dev/topics/db/queries/#limiting-querysets, принудительное использование параметра «step» синтаксиса фрагмента Python оценивает запрос. Это работает так:
Тем не менее, мне интересно, выполняется ли ограничение в срезах SQL или Python, весь возвращаемый массив результатов. Нет смысла извлекать огромные списки из памяти приложения.
источник
Да. Если вы хотите получить ограниченное подмножество объектов, вы можете использовать следующий код:
Пример:
Начало 0 необязательно, поэтому
Приведенный выше код возвращает первые 10 экземпляров.
источник
В качестве дополнения и наблюдения к другим полезным ответам, стоит заметить, что на самом деле выполнение
[:10]
срезов вернет первые 10 элементов списка , а не последние 10 ...Чтобы получить последние 10 вы должны сделать
[-10:]
вместо этого (см. Здесь ). Это поможет вам избежать использованияorder_by('-id')
с-
реверсом элементов.источник
Product.objects.filter(~Q(price=0))[-5:]
вызывает у меня ту же ошибку: «Отрицательное индексирование не поддерживается».