Поле Enum
Тип Enum создает столбец, значения которого
ограничены заранее заданным списком. Первым
параметром передается либо имя нативного
типа СУБД, либо список допустимых значений.
В моделях обычно применяется вместе с
Mapped и mapped_column.
Синтаксис
Enum(*enums, [name], [native_enum], [create_constraint])
Пример
Давайте создадим модель со столбцом статуса, который принимает только значения из списка:
from sqlalchemy import create_engine, Enum, select
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] = mapped_column(Enum('draft', 'published', 'archived'))
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
article = Article(title='article 1', status='draft')
session.add(article)
session.commit()
res = session.scalars(select(Article)).all()
print(res[0].status)
Результат выполнения кода:
"draft"
Пример
Давайте попробуем записать значение, которого нет в списке допустимых:
from sqlalchemy import create_engine, Enum
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] = mapped_column(Enum('draft', 'published', 'archived'))
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
article = Article(title='article 1', status='deleted')
session.add(article)
session.commit()
SQLAlchemy выбросит исключение:
"LookupError: 'deleted' is not among the defined enum values"
Пример
Давайте включим проверку на уровне базы данных
параметром create_constraint:
from sqlalchemy import create_engine, Enum
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]
status: Mapped[str] = mapped_column(
Enum('draft', 'published', 'archived', name='article_status', create_constraint=True)
)
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
print('table created')
Результат выполнения кода:
"table created"
Итоговый SQL запрос:
CREATE TABLE articles (
id INTEGER NOT NULL,
title VARCHAR NOT NULL,
status VARCHAR(9) NOT NULL,
PRIMARY KEY (id),
CONSTRAINT article_status CHECK (status IN ('draft', 'published', 'archived'))
)