ORM в Django основан на QuerySet. QuerySet — это набор объектов из базы данных, который может использовать фильтры для ограничения результатов. Уже известно, как получать один объект из базы данных с помощью метода get()
. Получить к нему доступ можно с помощью Post.objects.get()
. Каждая модель Django имеет как минимум один менеджер, а менеджер по умолчанию называется objects
. Сделать запрос к объекту (QuerySet
) можно с помощью менеджера модели. Для получения всех объектов из таблицы нужно просто использовать метод all()
в менеджере объектов по умолчанию:
>>> all_posts = Post.objects.all()
Таким образом можно создать QuerySet, который вернет все объекты базы данных. Но важно обратить внимание на то, что он не еще исполнился. QuerySet в Django ленивые. Они исполняются только в том случае, если их заставить. Это поведение делает инструмент крайне эффективным. Если не сохранить QuerySet в переменную, а написать его прямо в оболочку Python, выражение SQL в QuerySet исполнится автоматически, потому что такой была команда:
>>> Post.objects.all()
Метод filter()
Чтобы отфильтровать QuerySet, можно использовать метод filter()
менеджера. Например, можно получить все посты за 2017 год с помощью такого запроса:
Post.objects.filter(publish__year=2017)
Можно фильтровать и по нескольким полям одновременно. Так, чтобы получить все посты за 2017 год, написанные автором admin
, следует использовать команду:
Post.objects.filter(publish__year=2017, author__username='admin')
Это то же самое, что писать QuerySet с цепочкой фильтров:
Post.objects.filter(publish__year=2017) \
.filter(author__username='admin')
Запросы с методами поиска по полям пишутся с двумя нижними подчеркиваниями, например
publish__year
, _но такое же написание используется для получения доступа к полям связанных моделей, напримерauthor__username
.
Метод exclude()
Можно исключить некоторые результаты из запроса с помощью метода менеджера exclude()
. Например, можно получить все посты за 2017 год, названия которых не начинаются с Why
:
Post.objects.filter(publish__year=2017) \
.exclude(title__startswith='Why')
Метод order_by()
Результаты можно отсортировать по полям с помощью метода менеджера order_by()
. Например, можно получить все объекты, отсортированные согласно их названию (title
) с помощью такой команды:
Post.objects.order_by('title')
Подразумевается расположение по возрастанию. Чтобы разместить элементы по убыванию необходимо использовать минус в качестве префикса:
Post.objects.order_by('-title')
Удаление объектов
Если нужно удалить объект, это можно сделать из экземпляра с помощью метода delete()
:
post = Post.objects.get(id=1)
post.delete()
Обратите внимание, что удаление объектов также удалит все зависимые отношения для объектов
ForeignKey
, для которых вCASCADE
определеноon_delete
.
Когда исполняется QuerySet
Для QuerySet можно объединить несколько фильтров, но они не коснутся базы данных, до тех пор пока QuerySet не будет выполнен. А он исполняется в следующих условиях:
- При первой итерации по QuerySet.
- При получении среза, например
Post.objects.all()[:3]
. - При сериализации или кэшировании объектов.
- При вызове
repr()
илиlen()
. - При прямом вызове
list()
. - При проверке QuerySet в других выражениях, например
bool()
,or
,and
илиif
.