Работа с наборами запросов QuerySet и менеджерами
Теперь, когда у нас есть полнофункциональный сайт администрирования, чтобы управлять постами блога, самое время научиться программно читать контент из базы данных и писать его в базу данных.
Встроенный в Django объектно-реляционный преобразователь ORM(Object Relational Mapper) – это мощный API абстракции базы данных, который позволяет легко создавать, извлекать, обновлять и удалять объекты.
ORM-преобразователь дает возможность генерировать запросы на языке SQL, используя объектно-ориентированную парадигму Python. Его можно трактовать как способ взаимодействия с базой данных в Python’овском стиле вместо написания сырых SQL-запросов.
ORM-преобразователь соотносит модели с таблицами базы данных и предоставляет простой Python’овский интерфейс взаимодействия с базой данных.
ORM-преобразователь генерирует SQL-запросы и соотносит результаты с объектами модели.
ORM-преобразователь совместим с реляционными системами управления базами данных MySQL, PostgreSQL, SQLite, Oracle и MariaDB.
Напомним, что базу данных своего проекта можно определять в настроечном параметре DATABASES файла settings.py проекта. Django может работать с несколькими базами данных одновременно, при этом можно программировать маршрутизаторы баз данных, чтобы создавать конкретно-прикладные схемы маршрутизации данных.
После создания своих моделей данных Django предоставит бесплатный API для взаимодействия с ними.
Справочный материал по моделям данных находится в официальной документации на странице https://docs.djangoproject.com/en/5.0/ref/models/.
Встроенный в Django ORM-преобразователь основан на итерируемых наборах запросов QuerySet.
QuerySet – это коллекция запросов к базе данных, предназначенных для извлечения объектов из базы данных. К наборам запросов можно применять фильтры, чтобы сужать результаты запросов на основе заданных параметров.
Создание объектов
Выполните следующую ниже команду в командной оболочке, чтобы открыть оболочку Python:
python manage.py shell
Затем наберите следующие ниже строки:
from blog.models import Post, User
user = User.objects.get(username='admin')
post = Post(title='Another post', slug='another-post', body='Post body.', author=user)
post.save()
Давайте проанализируем работу приведенного выше исходного кода. Сначала мы извлекаем объект user с пользовательским именем admin:
user = User.objects.get(username='admin')
Метод get() позволяет извлекать из базы данных только один объект. Обратите внимание, что этот метод ожидает результат, совпадающий с запросом.
Если база данных не возвращает результатов, то указанный метод вызовет исключение DoesNotExist, а если база данных возвращает более одного результата, то он вызовет исключение MultipleObjectsReturned.
Оба исключения являются атрибутами модельного класса, на котором выполняется запрос.
Затем мы создаем экземпляр класса Post с конкретно-прикладным заголовком, слагом и телом и задаем пользователя, которого мы ранее извлекли, в качестве автора поста:
post = Post(title='Another post', slug='another-post', body='Post body.', author=user)
Этот объект находится в памяти и не сохраняется в базе данных, то есть мы создали объект Python, который можно использовать на стадии работы программы, но который не сохраняется в базе данных.
Наконец, мы сохраняем объект Post в базе данных, используя метод save():
post.save()
Приведенное выше действие за кулисами выполняет инструкцию SQL INSERT.
Сначала мы создали объект в памяти, а затем сохранили его в базе данных.
Создавать объект и сохранять его в базе данных также можно одной операцией, используя метод create().
Это делается следующим образом:
Post.objects.create(title='One more post', slug='one-more-post', body='Post body.', author=user)
Обновление объектов
Также мы можем изменять например заголовок поста на что-то другое и снова сохранять объект:
post.title = 'New title'
post.save()
На этот раз метод save() исполняет инструкцию SQL UPDATE.
Другой способ обновления объектов в БД предоставляет метод update() в сочетании с методом filter(), которые вместе выполняют один запрос к базе данных.
Предположим, что нам нужно обновить поле title в записи таблицы БД с id=2. Это можно сделать с помощью следующего кода:
Post.objects.filter(id=2).update(title="New title")
При таком подходе не нужно предварительно получать из БД обновляемый объект, что обеспечивает увеличение скорости взаимодействия приложения с БД.