Limit и Offset в Django QuerySet
В этом уроке вы узнаете, как ограничить QuerySet в Django, что эквивалентно предложениям LIMIT и OFFSET в SQL.
На практике вы редко получаете все строки из одной или нескольких таблиц в базе данных. Вместо этого используется подмножество строк для отображения на веб-странице.
Django использует синтаксис срезов, чтобы ограничить QuerySet определенным количеством объектов. За кулисами Django выполняет оператор SQL SELECT с предложениями LIMIT и OFFSET.
Предположим, вы хотите получить доступ к первым 10 строкам таблицы. Для этого можно использовать следующий срез:
Entity.objects.all()[:10]
Поскольку таблица хранит строки в неопределенном порядке, «первые 10 объектов» становятся непредсказуемыми.
Поэтому всегда следует сортировать результаты перед тем, как применить слайсинг к запросу. Например, следующий код получает первые 10 строк, упорядоченных по field_name:
Entity.objects.all().order_by(field_name)[:10]
Чтобы получить строки с 10 по 20, можно использовать следующую нарезку:
Entity.objects.all().order_by(field_name)[10:20]
В общем случае синтаксис ограничения результатов выглядит следующим образом:
Entity.objects.all()[Offset:Offset+Limit]
В этом синтаксисе Offset — это количество строк, которые вы хотите пропустить, а Limit — это количество строк, которые вы хотите извлечь.
Обратите внимание, что Django не поддерживает отрицательную индексацию, например:
Entity.objects.all().order_by(field_name)[-10]
Кроме того, при слайсинге QuerySet Django возвращает новый QuerySet.
Чтобы получить первую или последнюю строку, следует использовать метод first() или last(), поскольку если QuerySet пуст и вы используете срез:
Entity.objects.all().order_by(field_name)[0]
…то вы получите исключение IndexError.
Пример Limit Offset в Django
Для демонстрации мы будем использовать модель Employee из приложения HR. Модель Employee сопоставляется с таблицей hr_employee:
В следующем примере первые 10 сотрудников сортируются по именам:
>>> Employee.objects.all().order_by('first_name')[:10] SELECT "hr_employee"."id", "hr_employee"."first_name", "hr_employee"."last_name", "hr_employee"."contact_id", "hr_employee"."department_id" FROM "hr_employee" ORDER BY "hr_employee"."first_name" ASC LIMIT 10 Execution time: 0.000000s [Database: default] <QuerySet [<Employee: Aaron Pearson>, <Employee: Adam Crane>, <Employee: Adam Stewart>, <Employee: Adrienne Green>, <Employee: Alan Johnson>, <Employee: Alexa West>, <Employee: Alicia Wyatt>, <Employee: Amanda Benson>, <Employee: Amber Brown>, <Employee: Amy Lopez>]>
В следующем примере первые 10 строк пропускаются, а следующие 10 строк извлекаются из таблицы hr_employee:
>>> Employee.objects.order_by('first_name')[10:20] SELECT "hr_employee"."id", "hr_employee"."first_name", "hr_employee"."last_name", "hr_employee"."contact_id", "hr_employee"."department_id" FROM "hr_employee" ORDER BY "hr_employee"."first_name" ASC LIMIT 10 OFFSET 10 Execution time: 0.001001s [Database: default] <QuerySet [<Employee: Amy Lee>, <Employee: Andre Perez>, <Employee: Andrea Mcintosh>, <Employee: Andrew Dixon>, <Employee: Andrew Guerra>, <Employee: Ann Chang>, <Employee: Anne Odom>, <Employee: Anthony Fuentes>, <Employee: Anthony Welch>, <Employee: Ashley Brown>]>