Django ORM

Django-проект должен хранить массу данных: посты пользователей, информацию о самих пользователях, большое количество технической информации. Пора организовать взаимодействие кода проекта и базы данных.
Классы описывают новые типы объектов и позволяют создавать экземпляры таких объектов.
Записи в базах данных тоже описывают объекты — наборы свойств, которыми можно управлять. Вы уже пережили множество прекрасных мгновений, работая со SQL-запросами.
Есть способ связать данные объектов с записями в БД, упростить и автоматизировать стандартные операции, и при этом обойтись без запросов на SQL.
Это делает Django ORMObject-Relational Mapping, «объектно-реляционное отображение». Object — объекты, которые созданы на основе классов, relational — реляционные базы данных, а mapping — связь между системой объектов и базами данных.
Django ORM — это инструмент для работы с данными реляционной БД посредством классов, которые создаёт сам программист. Реализаций ORM существует много, работать мы будем с ORM, встроенной в Django.
Вот класс, описывающий данные для нашего проекта Yatube:
Скопировать код
Класс: Post Свойства: - Текст публикации - Дата публикации - Автор
Скопировать кодPYTHON
# так мы записывали обычные классы class Post: def __init__(self, text, pub_date, author): self.text = text self.pub_date = pub_date self.author = author
Классы, с которыми работает ORM, называются модели. Для них в Django есть специальный синтаксис.
Скопировать кодPYTHON
# так выглядит синтаксис модели - класса, с которым работает ORM class Post(models.Model): # класс Post, наследник класса Model из библиотеки models # свойство text типа TextField text = models.TextField() # свойство pub_date типа DateTimeField, текст "date published" это заголовок # поля в интерфейсе администратора. auto_now_add говорит, что при создании # новой записи автоматически будет подставлено текущее время и дата pub_date = models.DateTimeField("date published", auto_now_add=True) # свойство author типа ForeignKey, ссылка на модель User author = models.ForeignKey(User, on_delete=models.CASCADE)
Для всех моделей Django ORM создаст в БД таблицы. Описанные через синтаксис имя_свойства = models.тип_данных() свойства модели определят названия и типы данных в колонках таблицы БД.
Так, для модели Post в базе данных будет создана таблица с колонками text, pub_date и author, причём в колонке author должны быть указаны Primary Key записей из таблицы User.
Магия здесь в том, что после создания модели Django автоматически проведёт массу операций:
Впечатляющий список.

Подробный взгляд на модель

Модель, соответствующая нашей задаче, полностью выглядит так:
Скопировать кодPYTHON
from django.db import models from django.contrib.auth import get_user_model User = get_user_model() class Post(models.Model): text = models.TextField() pub_date = models.DateTimeField("date published", auto_now_add=True) author = models.ForeignKey(User, on_delete=models.CASCADE)
Первые строки импортируют нужные модули.
Всё, что относится к моделям, импортируется из модуля db в классе models
Скопировать кодPYTHON
# из модуля db импортируем класс models from django.db import models # из модуля auth импортируем функцию get_user_model from django.contrib.auth import get_user_model
В проекте Yatube мы дадим пользователям возможность регистрироваться и создавать свои страницы, и нам нужен инструмент для создания и администрирования аккаунтов. В Django встроена работа с пользователями. Для управления ими создана специальная модель User, и мы импортируем её. Официальная документация рекомендует обращаться к модели User через функцию get_user_model. Следуем этой рекомендации:
Скопировать кодPYTHON
User = get_user_model()
Описание модели начинается с объявления: класс Post — это наследник класса Model из модуля models.
Класс Model нужен для того, чтобы от него наследовались модели, классы, обрабатывающие данные. У класса Model есть множество предустановленных свойств и методов, обеспечивающих работу с БД.
Свойства модели связаны со столбцами таблицы в БД, а методы превращаются в запросы.
Скопировать кодPYTHON
class Post(models.Model): text = models.TextField() pub_date = models.DateTimeField("date published", auto_now_add=True) author = models.ForeignKey(User, on_delete=models.CASCADE)
Для свойств моделей указывают типы данных, соответствующие типам данных в БД.
В коде модели Post мы применили:
Параметр on_delete=models.CASCADE обеспечивает связность данных: если из таблицы User будет удалён пользователь, то будут удалены все связанные с ним посты.
Другие популярные типы полей:
В Django ORM есть и другие типы полей. Документация даёт полное описание базовых полей, но есть расширения, добавляющие новые типы полей или переопределяющие базовые типы.

Добавление модели в проект

Время кодить. Разместим код модели Post в проекте. В Django код моделей хранят в файлах models.py. Обычно такой файл создают в каждом приложении (app) проекта.
Вы создали приложение Posts, в его директории появился файл posts/models.py. По умолчанию в этом файле прописан только импорт модуля models:
Скопировать кодPYTHON
from django.db import models # Create your models here.
Добавьте в файл код модели Post. Теперь models.py должен выглядеть так:
Скопировать кодPYTHON
from django.db import models from django.contrib.auth import get_user_model User = get_user_model() class Post(models.Model): text = models.TextField() pub_date = models.DateTimeField("date published", auto_now_add=True) author = models.ForeignKey(User, on_delete=models.CASCADE, related_name="posts")
Обратите внимание на поле author. Оно ссылается на автора поста, на модель User, и для этого поля указано свойство related_name="posts".
Тут снова начинается магия: в каждом объекте модели User автоматически будет создано свойство с таким же названием (posts), и в нём будут храниться ссылки на все объекты модели Post, которые ссылаются на объект User.
На практике это означает, что в объекте записи есть поле author, в котором хранится ссылка на автора(например, admin), а в объекте пользователя admin появилось поле posts, в котором хранятся ссылки на все посты этого автора. И теперь можно получить список постов автора, обратившись к его свойству posts
В следующем уроке вы добавите модель в базу данных проекта.