Функция relationship
Функция relationship создает связь между
двумя моделями ORM. Первым параметром
передается имя связанного класса, а вторым
необязательным параметром - имя обратной связи
через back_populates. Связь позволяет
получать связанные объекты как атрибуты модели,
не выполняя SQL-запросы вручную.
Синтаксис
relationship(argument, [back_populates])
Пример
Давайте создадим две модели - User и
Article - и свяжем их через
relationship:
from sqlalchemy import create_engine, ForeignKey
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, Session
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = 'users'
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
articles: Mapped[list['Article']] = relationship(back_populates='user')
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
user_id: Mapped[int] = mapped_column(ForeignKey('users.id'))
user: Mapped['User'] = relationship(back_populates='articles')
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
user = User(name='user')
article = Article(title='article', user=user)
session.add(user)
session.commit()
print(user.articles[0].title)
print(article.user.name)
Результат выполнения кода:
"article"
"user"
Пример
Давайте свяжем модели параметром backref,
который создает обратную связь автоматически:
from sqlalchemy import create_engine, ForeignKey
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, Session
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = 'users'
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
user_id: Mapped[int] = mapped_column(ForeignKey('users.id'))
user: Mapped['User'] = relationship(backref='articles')
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
user = User(name='user')
article = Article(title='article', user=user)
session.add(user)
session.commit()
print(article.user.name)
print(user.articles[0].title)
Результат выполнения кода:
"user"
"article"
Пример
Давайте укажем стратегию загрузки lazy='joined',
чтобы связанные объекты подгружались сразу:
from sqlalchemy import create_engine, ForeignKey
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, Session
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = 'users'
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
articles: Mapped[list['Article']] = relationship(
back_populates='user',
lazy='joined'
)
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
user_id: Mapped[int] = mapped_column(ForeignKey('users.id'))
user: Mapped['User'] = relationship(back_populates='articles')
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
user = User(name='user')
article = Article(title='article', user=user)
session.add(user)
session.commit()
res = session.query(User).first()
print(res.articles[0].title)
Результат выполнения кода:
"article"
Смотрите также
-
параметр
backref,
который создает обратную связь автоматически -
функцию
foreign,
которая указывает удаленный столбец для связи -
функцию
joinedload,
которая жадно загружает связанные объекты через JOIN -
функцию
selectinload,
которая загружает связь отдельным SELECT IN запросом