Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Работа с моделями Python: Разработка на фреймворке Django

Модель в MVC v2 – это слой приложения, который отвечает за связь с предметной областью. В нем находится вся бизнес-логика приложения. Для простоты реализации, сюда часто включают механизмы для работы с базой данных.

Модель, как слой, существует независимо от фреймворка, HTTP и веба в целом. Вся остальная система может обращаться к моделям, но модели не могут знать и не знают ничего про среду, в которой они выполняются.

Это значит, что мы можем работать с моделями через специальный вариант REPL, который работает в контексте фреймворка командой python manage.py shell.

Создадим новую статью, наполним ее данными и сохраним в базе:

python manage.py shell
from hexlet_django_blog.article.models import Article # Импортируем наш класс модели Article
a = Article()
# Когда объект модели создан, его можно наполнять данными через обычные свойства.
a.name = 'my super article'
a.body = 'my content'
a # <Article: Article object (None)>
a.id
a.name # 'my super article'
a.body # 'my content'

Также можно создать объект методом create

from hexlet_django_blog.article.models import Article

a = Article.objects.create(name='my super article', body='my content')

Когда объект готов, его можно сохранить в базу данных. Для этого надо вызвать метод save():

a.save()
a # <Article: Article object (1)>
a.id # 1
a.name # 'my super article'
a.body # 'my content'
a.timestamp # datetime.datetime(2022, 11, 3, 20, 48, 19, 883732, tzinfo=datetime.timezone.utc)

Этот метод делает запрос INSERT в базу данных. Затем он обновляет сам объект:

  • Внутрь записывается идентификатор статьи, взятый из базы данных
  • Заполняется поле timestamp.

Созданный объект можно тут же поменять:

a.name = 'another title'
a.name # 'another title'

Изменение свойств не затрагивает базу данных. Это происходит только на уровне самого объекта. Если в этот момент закрыть консоль, то все изменения потеряются. Для сохранения нужно снова вызвать save(). Этот метод универсальный, он подходит как для создания новой сущности, так и для ее обновления:

a.save()
a # <Article: Article object (1)>
a.id # 1
a.name # 'another title'
a.body # 'my content'
a.timestamp # datetime.datetime(2022, 11, 3, 20, 48, 19, 883732, tzinfo=datetime.timezone.utc)

Теперь предположим, что у нас нет переменной с текущей статьей. Например, мы перезапустили консоль. Получить нужный объект можно с помощью статических методов, которые появляются у каждой модели. Самый простой способ достать запись, сделать поиск по ее идентификатору:

a = Article.objects.get(id=1)
a # <Article: Article object (1)>
a.id # 1
a.name # 'another title'
a.body # 'my content'
a.timestamp # datetime.datetime(2022, 11, 3, 20, 48, 19, 883732, tzinfo=datetime.timezone.utc)

Article.objects — это представление всех объектов данной модели. get ищет одну запись по заданному условию и возвращает запись. Если запись не найдена, то вызовется исключение:

a = Article.objects.get(id=2)
# Traceback (most recent call last):
#     ...
# DoesNotExist: Question matching query does not exist.

Если нужен поиск по полям, который вернет коллекцию, для этого подходит метод filter:

a = Article.objects.filter(name='another title')
a # <QuerySet [<Article: Article object (1)>]>

Мы можем составить и более сложный запрос. Предположим, что надо вывести body первой записи, у которой это id больше 50 (при условии, что записей в таблице больше 50):

Article.objects.filter(id__gt=50).first().body # 'my content'

Здесь строится целая цепочка вызова методов. И такие цепочки могут быть достаточно длинными. Каждый из шагов уточняет запрос по тому или иному критерию, а в конце всегда стоит вызов какого-то метода. Он определяет, сколько записей мы хотим получить. В данном случае мы хотим получить одну первую попавшуюся. Поэтому запрос заканчивается вызовом метода .first(). А .body мы уже получаем у объекта, который является результатом выполнения запроса.

Во фрагменте указано условие, по которому выбираются объекты в запросе — id__gt=50. Это так называемый lookup. id здесь означает имя поля, а дальше через разделитель "__" (двойное подчеркивание) указывается gt — сокращение от greater than (больше чем) и, наконец, само значение.

Такой синтаксис приходится использовать, так как мы не можем при вызове метода указать аргумент id > 20. Авторы вышли из ситуации и использовали именованные аргументы с такими необычными именами.

Попробуем запросить данные из базы данных и вывести список всех записей модели Article:

a = Article.objects.all()
a # <QuerySet [<Article: Article object (1)>]>

И последнее, что можно сделать с сущностью, это удалить ее:

a = Article.objects.get(id=1)
a.delete() # (1, {'article.Article': 1})
Article.objects.all() # <QuerySet []>

Самостоятельная работа

  1. Создайте пять статей через репл. Они понадобятся при построении CRUD

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Об обучении на Хекслете

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
от 6 300 ₽ в месяц
Разработка веб-приложений на Django
10 месяцев
с нуля
Старт 25 апреля

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»