Django - ограничение результатов запроса - PullRequest
163 голосов
/ 04 июля 2011

Я хочу взять последние 10 экземпляров модели и иметь этот код:

 Model.objects.all().order_by('-id')[:10]

Правда ли, что сначала подбирают все экземпляры, а затем берут только 10 последних? Есть ли более эффективный метод?

Ответы [ 6 ]

258 голосов
/ 04 июля 2011

Наборы запросов 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>]
30 голосов
/ 04 июля 2011

На самом деле я думаю, что LIMIT 10 будет выдано базе данных, поэтому срезы будут происходить не в Python, а в базе данных.

См. limit-querysets для получения дополнительной информации.

12 голосов
/ 09 января 2015

Похоже, что решение в вопросе больше не работает с Django 1.7 и выдает ошибку: «Невозможно изменить порядок запроса после того, как был взят фрагмент» *

Согласно документации https://docs.djangoproject.com/en/dev/topics/db/queries/#limiting-querysets форсирование параметра «step» синтаксиса фрагмента Python оценивает запрос.Это работает следующим образом:

Model.objects.all().order_by('-id')[:10:1]

Тем не менее, мне интересно, выполняется ли ограничение в срезах SQL или Python, весь возвращаемый массив результатов.Нет смысла извлекать огромные списки из памяти приложения.

2 голосов
/ 19 апреля 2018

Да. Если вы хотите получить ограниченное подмножество объектов, вы можете использовать следующий код:

Пример:

obj=emp.objects.all()[0:10]

Начало 0 необязательно, поэтому

obj=emp.objects.all()[:10]

Приведенный выше код возвращает первые 10 экземпляров.

1 голос
/ 04 сентября 2018

В качестве дополнения и наблюдения к другим полезным ответам, стоит заметить, что на самом деле выполнение [:10] в качестве нарезки вернет первых 10 элементов списка , а не последних 10 ...

Чтобы получить последние 10, вы должны вместо этого сделать [-10:] (см. здесь ).Это поможет вам избежать использования order_by('-id') с - для реверсирования элементов.

0 голосов
/ 28 февраля 2017

Это не то, что на самом деле происходит.Джанго НЕ получает только необходимые результаты.Django загрузит полную таблицу базы данных (что является глупостью [id)) и вернет вам только последние 10 записей.

Я подтвердил это, запустив SHOW FULL PROCESSLIST на сервере MySQL, и запросНЕ содержит предложение LIMIT.

Django НЕ является хорошим вариантом, если вы собираетесь разрабатывать большое приложение, требующее высокой масштабируемости.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...