Функция backref
Функция backref создает обратную связь
между двумя моделями. Она передается в параметр
backref функции relationship и позволяет
обращаться к связанным объектам с другой стороны
отношения. Первым параметром функция принимает
имя атрибута для обратной связи. Дополнительные
параметры позволяют настроить загрузку и поведение
связанных объектов.
Синтаксис
backref(name, [lazy], [uselist], [cascade])
Пример
Давайте создадим две модели 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]
articles: Mapped[list['Article']] = relationship(backref='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'))
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.add(article)
session.commit()
print(article.user.name)
print(user.articles[0].title)
Результат выполнения кода:
"user"
"article"
Пример
Давайте настроим каскадное удаление через
backref с параметром cascade:
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(
backref='user',
cascade='all, delete-orphan'
)
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'))
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()
session.delete(user)
session.commit()
res = session.query(Article).all()
print(res)
Результат выполнения кода:
[]
Пример
Давайте используем backref с параметром
lazy для отложенной загрузки:
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(
backref='user',
lazy='select'
)
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'))
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.add(article)
session.commit()
loaded_user = session.get(User, user.id)
print(loaded_user.articles)
Результат выполнения кода:
[<Article(id=1, title='article', user_id=1)>]
Смотрите также
-
функцию
relationship,
которая создает связь между моделями -
функцию
foreign,
которая указывает внешний ключ для связи -
функцию
selectinload,
которая загружает связанные объекты одним запросом -
функцию
joinedload,
которая загружает связанные объекты через JOIN