Атрибут naming_convention
Атрибут naming_convention класса MetaData
задает словарь шаблонов имен для автоматического
именования ограничений базы данных: первичных ключей,
внешних ключей, уникальных ограничений, индексов
и проверок. Первым параметром передается словарь,
где ключи - это типы ограничений, а значения -
строковые шаблоны с подстановочными полями.
По умолчанию SQLAlchemy не назначает имена ограничениям, и база данных генерирует их сама. Это затрудняет управление миграциями, поэтому рекомендуется задавать соглашение об именовании явно.
Синтаксис
MetaData(naming_convention={
'pk': 'pk_%(table_name)s',
'fk': 'fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s',
'ix': 'ix_%(column_0_label)s',
'uq': 'uq_%(table_name)s_%(column_0_name)s',
'ck': 'ck_%(table_name)s_%(constraint_name)s'
})
Пример
Давайте создадим метаданные с соглашением об именовании и опишем модель:
from sqlalchemy import MetaData, Integer, String
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
metadata = MetaData(naming_convention={
'pk': 'pk_%(table_name)s',
'ix': 'ix_%(column_0_label)s',
'uq': 'uq_%(table_name)s_%(column_0_name)s',
'ck': 'ck_%(table_name)s_%(constraint_name)s',
'fk': 'fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s'
})
class Base(DeclarativeBase):
metadata = metadata
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str] = mapped_column(String(50), unique=True)
text: Mapped[str] = mapped_column(String(200))
print(Article.__table__.primary_key)
Результат выполнения кода:
PrimaryKeyConstraint(Column('id', Integer(), table=<articles>, primary_key=True, nullable=False), name='pk_articles')
Пример
Давайте посмотрим, как именуются уникальные ограничения и индексы при заданном соглашении:
from sqlalchemy import MetaData, Integer, String
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
metadata = MetaData(naming_convention={
'pk': 'pk_%(table_name)s',
'ix': 'ix_%(column_0_label)s',
'uq': 'uq_%(table_name)s_%(column_0_name)s',
'ck': 'ck_%(table_name)s_%(constraint_name)s',
'fk': 'fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s'
})
class Base(DeclarativeBase):
metadata = metadata
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str] = mapped_column(String(50), unique=True, index=True)
text: Mapped[str] = mapped_column(String(200))
for constraint in Article.__table__.constraints:
print(constraint.name)
Результат выполнения кода:
"pk_articles"
"uq_articles_title"
Пример
Давайте создадим две связанные таблицы и посмотрим, как именуется внешний ключ:
from sqlalchemy import MetaData, Integer, String, ForeignKey
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
metadata = MetaData(naming_convention={
'pk': 'pk_%(table_name)s',
'ix': 'ix_%(column_0_label)s',
'uq': 'uq_%(table_name)s_%(column_0_name)s',
'ck': 'ck_%(table_name)s_%(constraint_name)s',
'fk': 'fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s'
})
class Base(DeclarativeBase):
metadata = metadata
class User(Base):
__tablename__ = 'users'
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(50))
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str] = mapped_column(String(50))
user_id: Mapped[int] = mapped_column(ForeignKey('users.id'))
for constraint in Article.__table__.constraints:
if constraint.name and constraint.name.startswith('fk'):
print(constraint.name)
Результат выполнения кода:
"fk_articles_user_id_users"
Пример
Давайте сгенерируем SQL-запрос на создание таблицы с именованными ограничениями:
from sqlalchemy import MetaData, Integer, String
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from sqlalchemy.schema import CreateTable
metadata = MetaData(naming_convention={
'pk': 'pk_%(table_name)s',
'ix': 'ix_%(column_0_label)s',
'uq': 'uq_%(table_name)s_%(column_0_name)s',
'ck': 'ck_%(table_name)s_%(constraint_name)s',
'fk': 'fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s'
})
class Base(DeclarativeBase):
metadata = metadata
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str] = mapped_column(String(50), unique=True)
text: Mapped[str] = mapped_column(String(200))
print(CreateTable(Article.__table__).compile())
Итоговый SQL запрос:
CREATE TABLE articles (
id INTEGER NOT NULL,
title VARCHAR(50) NOT NULL,
text VARCHAR(200) NOT NULL,
PRIMARY KEY (id),
CONSTRAINT uq_articles_title UNIQUE (title)
)
Смотрите также
-
класс
MetaData,
который хранит информацию о схеме базы данных -
атрибут
tables,
который содержит словарь всех таблиц метаданных -
атрибут
sorted_tables,
который возвращает таблицы в порядке создания -
метод
create_all,
который создает все таблицы в базе данных