Django 5 для начинающих

Прогресс по курсу:  9/1004

3.3 Первые ORM запросы (CRUD)
4 из 15 шагов пройдено
0 из 49 баллов  получено

Чтение данных из БД

В 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.


  • Комментария
Будьте вежливы и соблюдайте наши принципы сообщества. Пожалуйста, не оставляйте решения и подсказки в комментариях, для этого есть отдельный форум.
Оставить комментарий
from .models import Person
 
posts = Post.objects.all()[5:10]
for post in posts:
    print(f"{post.id}, {post.title}")

Здесь наверно необходимо импортировать класс Post а не Person (к данному классу мы в теле кода не обращаемся)

@Евгений_Епишкин, Спасибо, исправили.

После решения задачи 3.3.11 подозреваю что у вас тут ошибка?

@Максим_Михеев, спасибо, исправил.