Функция remote
Функция remote из секции rel помечает
столбец внешнего ключа как удаленный источник
значения для связи. Она применяется в случаях,
когда вторичный ключ связи не совпадает с
локальным столбцом таблицы, и SQLAlchemy
не может самостоятельно определить, какой
именно внешний ключ участвует в соединении.
Чаще всего remote используется внутри
аргумента primaryjoin или
secondaryjoin функции relationship.
Функция принимает одно выражение - столбец
внешнего ключа - и возвращает его же,
но помеченным как удаленный.
Синтаксис
from sqlalchemy.orm import remote
remote(column)
Пример
Давайте опишем две модели, связанные составным
внешним ключом, и укажем удаленный столбец
через remote:
from sqlalchemy import create_engine, ForeignKey
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, remote
class Base(DeclarativeBase):
pass
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
class Comment(Base):
__tablename__ = 'comments'
id: Mapped[int] = mapped_column(primary_key=True)
article_id: Mapped[int] = mapped_column(ForeignKey('articles.id'))
text: Mapped[str]
article: Mapped['Article'] = relationship(
primaryjoin=remote(article_id) == Article.id
)
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
print('ok')
Результат выполнения кода:
"ok"
Пример
Давайте загрузим связанный объект и убедимся, что связь работает:
from sqlalchemy import create_engine, ForeignKey, select
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, remote, Session
class Base(DeclarativeBase):
pass
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
class Comment(Base):
__tablename__ = 'comments'
id: Mapped[int] = mapped_column(primary_key=True)
article_id: Mapped[int] = mapped_column(ForeignKey('articles.id'))
text: Mapped[str]
article: Mapped['Article'] = relationship(
primaryjoin=remote(article_id) == Article.id
)
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
article = Article(id=1, title='article')
comment = Comment(id=1, article_id=1, text='text')
session.add_all([article, comment])
session.commit()
res = session.scalar(select(Comment).where(Comment.id == 1))
print(res.article.title)
Результат выполнения кода:
"article"
Пример
Давайте применим remote вместе с
foreign в составном соединении:
from sqlalchemy import create_engine, ForeignKey
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, remote, foreign
class Base(DeclarativeBase):
pass
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
class Comment(Base):
__tablename__ = 'comments'
id: Mapped[int] = mapped_column(primary_key=True)
article_id: Mapped[int] = mapped_column(ForeignKey('articles.id'))
text: Mapped[str]
article: Mapped['Article'] = relationship(
primaryjoin=foreign(article_id) == remote(Article.id)
)
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
print('ok')
Результат выполнения кода:
"ok"
Смотрите также
-
функцию
foreign,
которая помечает столбец как внешний -
функцию
relationship,
которая настраивает связь между моделями -
функцию
backref,
которая создает обратную ссылку в связи -
параметр
lazy='select',
который задает стратегию загрузки связи