Блог на Django #12: Методы QuerySet

2281

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')
Python data course

Это то же самое, что писать 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.

Тест на знание python

Какая функция разворачивает список задом наперед?
Какой будет результат выполнения этого кода?
Что выведет этот код?
Что выведет этот код?
Какой будет результат выполнения этого кода?
Александр
Я создал этот блог в 2018 году, чтобы распространять полезные учебные материалы, документации и уроки на русском. На сайте опубликовано множество статей по основам python и библиотекам, уроков для начинающих и примеров написания программ. Пишу на популярные темы: веб-разработка, работа с базами данных, data sciense и другие...