Чтение данных из БД
В Django получить значение данных из БД можно несколькими методами, рассмотрим часто используемые из них:
get()- для одного объекта;
all()- для всех объектов;
filter()- для группы объектов по фильтру;
exclude()- для группы объектов с исключением некоторых;
Методы all(), filter() и exclude() возвращают объект QuerySet. Это, по сути, некое промежуточное хранилище, в котором содержится информация, полученная из БД.
Объект QuerySet может быть создан, отфильтрован и затем использован фактически без выполнения запросов к базе данных. База данных не будет затронута, пока вы не инициируете новое выполнение QuerySet. Рассмотрим последовательно все указанные методы.
Метод get()
Он возвращает один объект по определенному условию, которое передается в качестве параметра:
>>> my_post = Post.objects.get(id=1) # получаем запись с id=1
>>> my_post
<Post: Я учусь работать с Django!> # Проверяем что получили
>>> my_post = Post.objects.get(text='Мой второй текст в БД') # получаем запись проверяя содержание поля text
>>> my_post
<Post: Мой второй текст в БД> # Проверяем что получили
При использовании этого метода надо учитывать, что он предназначен для выборки таких объектов, которые имеются в единичном числе в базе данных.
Если в таблице не окажется подобного объекта, то мы получим ошибку имя_модели.DoesNotExist.
Если же в таблице будет несколько объектов, которые соответствуют условию, то будет сгенерировано исключение MultipleObjectsReturned.
Поэтому следует применять данный метод с осторожностью, либо применять обработку соответствующих исключений:
Метод all()
Если необходимо получить все имеющиеся объекты, то применяется метод all():
posts = Post.objects.all()
Данный метод возвращает объект типа QuerySet.
Также мы можем далее распаковывать содержимое нашего QuerySet, для этого напишем следующий код:
>>> posts = Post.objects.all()
>>> posts
<QuerySet [<Post: Я учусь работать с Django!>, <Post: Мой второй текст в БД>, <Post: Моя третья запись в БД>]>
>>> for post in posts:
... print(post.id, post.text)
И получим следующий результат:
Метод filter()
Если надо получить все объекты, которые соответствуют определенному критерию, то применяется метод filter(), который в качестве параметра принимает критерий выборки:
>>> post = Post.objects.filter(id=3)
>>> post
<QuerySet [<Post: Моя третья запись в БД>]>
Также мы можем указать несколько условий:
>>> post = Post.objects.filter(id=3, text='Моя третья запись в БД')
>>> post
<QuerySet [<Post: Моя третья запись в БД>]>
Метод filter() позволяет определять более сложные условия.
Метод exclude()
Метод exclude() позволяет исключить из выборки записи, которые соответствуют переданному в качестве параметра критерию:
>>> post = Post.objects.exclude(id=3)
>>> post
<QuerySet [<Post: Я учусь работать с Django!>, <Post: Мой второй текст в БД>]>
Можно комбинировать два выше рассмотренных метода, например когда у нас больше полей:
# выбираем всех пользователей, у которых name="Tom" кроме тех, у которых age=23
people = Person.objects.filter(name="Tom").exclude(age=23)
Ограничение количества
С помощью синтаксиса списков можно получить определенную порцию данных из QuerySet:
>>> post = Post.objects.all()[:2]
>>> post
<QuerySet [<Post: Я учусь работать с Django!>, <Post: Мой второй текст в БД>]>
В данном случае выбираем первые 2 объекта, что на уровне базы данных транслируется в SQL-выражение: LIMIT 2
Например, если бы имели больше записей в БД, мы могли бы указать первый параметр сколько объектов надо пропустить:
from .models import Post
posts = Post.objects.all()[5:10]
for post in posts:
print(f"{post.id}, {post.title}")
В данном случае пропускаем первые 5 объектов и выбираем следующие 5 объектов до 10-го индекса, что на уровне базы данных транслируется в выражение OFFSET 5 LIMIT 5.