JavaRush /Курсы /Модуль 4: FastAPI /Создание моделей данных с использованием SQLAlchemy

Создание моделей данных с использованием SQLAlchemy

Модуль 4: FastAPI
6 уровень , 2 лекция
Открыта

Модели данных можно смело назвать основой приложения. Именно они определяют форму и структуру данных, с которыми оно будет работать. Ну а SQLAlchemy — это такой удобный способ описания этих моделей с помощью Python-классов. При этом SQLAlchemy спроектирован так, что вам — разработчику — не нужно концентрироваться на сложностях SQL, можно сосредоточить внимание на логике.

Как классы в ООП, модели данных напоминают формочки для печенья. Вы определяете "формочку" (то есть модель) один раз, а затем используете её для создания множества однотипных "печенек" (то есть конкретных записей в базе данных).


Основы создания моделей

Каждая модель SQLAlchemy — это класс, который наследуется от базового класса Base. Этот базовый класс отвечает за связь модели с таблицей в базе данных. В SQLAlchemy для создания Base используется конструкция:


from sqlalchemy.orm import declarative_base

Base = declarative_base()

Давайте создадим нашу первую модель — модель пользователя (User).


from sqlalchemy import Column, Integer, String

class User(Base):
    __tablename__ = 'users'  # Указываем имя таблицы

    id = Column(Integer, primary_key=True)  # Первичный ключ
    name = Column(String, nullable=False)  # Столбец для имени
    email = Column(String, unique=True, nullable=False)  # Уникальный и обязательный столбец

    def __repr__(self):
        return f"<User(name={self.name!r}, email={self.email!r})>"

Что мы сделали:

  • Указали имя таблицы через __tablename__.
  • Определили поля таблицы (столбцы) как атрибуты класса, используя Column.
  • Добавили типы данных для каждого столбца (Integer, String).
  • Реализовали метод __repr__ для более удобного отображения объекта.

Теперь модель User представляет таблицу users в нашей базе данных.


Определение таблиц и столбцов

В таблицах базы данных есть разные типы данных. SQLAlchemy поддерживает множество типов: Integer, String, Float, Boolean, DateTime и другие. Давайте разберём, как использовать эти типы и добавлять дополнительные поля.

Допустим, наша модель пользователя также должна хранить дату регистрации и статус, указывающий, активен ли пользователь. Добавим их:


from sqlalchemy import Boolean, DateTime
from datetime import datetime

class User(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    name = Column(String, nullable=False)
    email = Column(String, unique=True, nullable=False)
    is_active = Column(Boolean, default=True)  # Булевое значение с умолчанием
    registered_at = Column(DateTime, default=datetime.utcnow)  # Используем текущую дату

    def __repr__(self):
        return f"<User(name={self.name!r}, email={self.email!r})>"

Теперь таблица users будет содержать два новых столбца:

  • is_active — булевое значение для статуса активности;
  • registered_at — дата и время регистрации.

Пример создания сложной модели

Реальная жизнь — это не только "имя" и "email". Ваши модели могут быть сложными, включая ограничения, индексы и даже пользовательские типы данных. Давайте создадим модель для продуктов, включающую цену и категорию.


from sqlalchemy import ForeignKey, Float

class Product(Base):
    __tablename__ = 'products'

    id = Column(Integer, primary_key=True)
    name = Column(String, nullable=False)
    price = Column(Float, nullable=False)
    category_id = Column(Integer, ForeignKey('categories.id'))  # Внешний ключ для категории

    def __repr__(self):
        return f"<Product(name={self.name!r}, price={self.price!r})>"

Эта модель показывает:

  1. Как использовать тип Float для хранения чисел с плавающей точкой.
  2. Как связать модель с другой таблицей через ForeignKey.

Создание связанных таблиц

Для полноты картины нам нужно создать таблицу categories, на которую ссылается Product.


class Category(Base):
    __tablename__ = 'categories'

    id = Column(Integer, primary_key=True)
    name = Column(String, nullable=False, unique=True)

    def __repr__(self):
        return f"<Category(name={self.name!r})>"

Теперь у нас есть модель Category, к которой привязаны продукты. Мы сможем создавать категории и связывать их с товарами.


Обработка ограничений и индексов

SQLAlchemy позволяет добавлять ограничения, такие как уникальность (unique) или условие обязательного наличия данных (nullable=False). Добавим индекс на поле email в модели пользователя:


from sqlalchemy import Index

Index('idx_email', User.email)  # Создание индекса

Индексы ускоряют поиск определённых данных, например, электронной почты. Это особенно важно для полей, которые часто используются в запросах.


Практическая демонстрация

Давайте создадим небольшую базу данных SQLite и создадим таблицы на основе наших моделей.


from sqlalchemy import create_engine

# Подключение SQLite (или другой базы данных)
engine = create_engine('sqlite:///example.db', echo=True)  # echo=True для логирования SQL

# Создание всех таблиц
Base.metadata.create_all(engine)

print("Таблицы успешно созданы!")

После выполнения кода мы увидим детальные логи выполнения SQL-запросов для создания таблиц.


Зачем это нужно?

Почему мы используем ORM и SQLAlchemy вместо ручного написания SQL? Потому что ORM:

  1. Упрощает чтение и поддержку кода.
  2. Позволяет абстрагироваться от конкретной базы данных.
  3. Автоматизирует многие рутинные задачи, такие как преобразование данных между Python и SQL.

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

SQLAlchemy, в отличие от Django ORM, предоставляет больше контроля над SQL-запросами. Это делает его отличным выбором для сложных проектов.


Типичные ошибки

  1. Пропущенный __tablename__. Если забыть указать имя таблицы, SQLAlchemy не поймёт, как связать модель с таблицей.
  2. Несоответствие типов данных. Убедитесь, что типы данных в модели соответствуют типам в базе данных. Например, String должен иметь ограничение длины для совместимости с некоторыми базами.
  3. Отсутствие первичного ключа. Каждая таблица должна иметь хотя бы один первичный ключ (обычно поле id).

Итоговая структура проекта

На этом этапе у нас есть:

  1. Таблица пользователей (User), включающая имя, email, активность и дату регистрации.
  2. Таблица продуктов (Product) с ценой и категорией.
  3. Таблица категорий (Category) для связи.

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

1
Задача
Модуль 4: FastAPI, 6 уровень, 2 лекция
Недоступна
Создание простой модели
Создание простой модели
1
Задача
Модуль 4: FastAPI, 6 уровень, 2 лекция
Недоступна
Создание реляционной модели
Создание реляционной модели
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ