Класс Mapped
Класс Mapped используется для
аннотирования атрибутов декларативной модели.
Он указывает SQLAlchemy, что атрибут является
колонкой таблицы, а не обычным полем класса.
В качестве параметра класс принимает тип Python,
который соответствует типу колонки в базе данных,
например int, str или bool.
При этом сам объект Mapped в рантайме
не хранит значение, а служит лишь метаданными
для маппера.
Синтаксис
Mapped[тип]
Пример
Давайте объявим простую модель с аннотациями
через Mapped:
from sqlalchemy import create_engine
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
class Base(DeclarativeBase):
pass
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
text: Mapped[str]
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
print(Article.__table__.columns.keys())
Результат выполнения кода:
['id', 'title', 'text']
Пример
Давайте создадим объект модели и убедимся, что атрибуты работают как обычные поля:
from sqlalchemy import create_engine
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
class Base(DeclarativeBase):
pass
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
status: Mapped[str]
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
article = Article(title='article', status='draft')
session.add(article)
session.commit()
print(article.id, article.title, article.status)
Результат выполнения кода:
"1 article draft"
Пример
Давайте используем необязательный тип
Optional для колонки, которая может
принимать значение None:
from typing import Optional
from sqlalchemy import create_engine
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
class Base(DeclarativeBase):
pass
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
text: Mapped[Optional[str]]
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
article = Article(title='article', text=None)
print(article.title, article.text)
Результат выполнения кода:
"article None"
Пример
Давайте посмотрим, как Mapped
влияет на генерацию SQL-запроса при вставке:
from sqlalchemy import create_engine
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
class Base(DeclarativeBase):
pass
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
num: Mapped[int]
engine = create_engine('sqlite:///:memory:', echo=True)
Base.metadata.create_all(engine)
with Session(engine) as session:
session.add(Article(title='article', num=10))
session.commit()
Итоговый SQL запрос:
INSERT INTO articles (title, num) VALUES (?, ?)
Смотрите также
-
класс
mapped_column,
который настраивает колонку модели -
класс
DeclarativeBase,
который служит базой для декларативных моделей -
атрибут
__tablename__,
который задает имя таблицы модели -
класс
MappedAsDataclass,
который превращает модель в датакласс