Подтвердить что ты не робот

Django - ограничение результатов запроса

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

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

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

4b9b3361

Ответ 1

Запросы 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>]

Ответ 2

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

Подробнее см. limiting-querysets.

Ответ 3

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

В соответствии с документацией https://docs.djangoproject.com/en/dev/topics/db/queries/#limiting-querysets, заставляющей параметр "шаг" синтаксиса среза Python оценивает запрос. Он работает следующим образом:

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

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

Ответ 4

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

Пример:

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

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

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

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

Ответ 5

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

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

Ответ 6

Для меня параметр Python Steps делает свою работу, как ответил Николай Грищенко:

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

Обратите внимание, что это специфично для noSQL/mongodb

Ответ 7

Нет, это не так, как это четко объяснено в документации.

Ответ 8

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

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

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