与其他类的关系是以通常的方式完成的,其中添加了类指定给 relationship()
可以是字符串名称。与 Base
在映射器编译时用于将名称解析为实际类对象,一旦使用了映射器配置,该对象将被定义为::
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(50))
addresses = relationship("Address", backref="user")
class Address(Base):
__tablename__ = 'addresses'
id = Column(Integer, primary_key=True)
email = Column(String(50))
user_id = Column(Integer, ForeignKey('users.id'))
列构造,因为它们只是这样,所以可以立即使用,如下所示,我们在其中定义了 Address
使用它们的类:
class Address(Base):
__tablename__ = 'addresses'
id = Column(Integer, primary_key=True)
email = Column(String(50))
user_id = Column(Integer, ForeignKey('users.id'))
user = relationship(User, primaryjoin=user_id == User.id)
除了 relationship()
,依赖尚未定义的类上的列的其他参数也可以指定为字符串。这些字符串被计算为python表达式。此评估中可用的完整命名空间包括为此声明性基映射的所有类,以及 sqlalchemy
包,包括表达式函数 desc()
和 func
::
class User(Base):
# ....
addresses = relationship("Address",
order_by="desc(Address.email)",
primaryjoin="Address.user_id==User.id")
对于多个模块包含相同名称的类的情况,也可以将字符串类名称指定为这些字符串表达式中的模块限定路径::
class User(Base):
# ....
addresses = relationship("myapp.model.address.Address",
order_by="desc(myapp.model.address.Address.email)",
primaryjoin="myapp.model.address.Address.user_id=="
"myapp.model.user.User.id")
限定路径可以是消除名称之间不明确的任何部分路径。例如,消除 myapp.model.address.Address
和 myapp.model.lookup.Address
,我们可以指定 address.Address
或 lookup.Address
::
class User(Base):
# ....
addresses = relationship("address.Address",
order_by="desc(address.Address.email)",
primaryjoin="address.Address.user_id=="
"User.id")
使用基于字符串的属性也有两种选择。还可以使用lambda,在配置了所有映射器之后将对其进行计算::
class User(Base):
# ...
addresses = relationship(lambda: Address,
order_by=lambda: desc(Address.email),
primaryjoin=lambda: Address.user_id==User.id)
或者,可以在类可用后显式地将关系添加到类中::
User.addresses = relationship(Address,
primaryjoin=Address.user_id==User.id)
许多对多关系的声明方式与传统映射的声明方式相同。这个 secondary
参数 relationship()
像往常一样通过了 Table
对象,通常以传统方式声明。这个 Table
通常分享 MetaData
声明性基使用的对象:
keywords = Table(
'keywords', Base.metadata,
Column('author_id', Integer, ForeignKey('authors.id')),
Column('keyword_id', Integer, ForeignKey('keywords.id'))
)
class Author(Base):
__tablename__ = 'authors'
id = Column(Integer, primary_key=True)
keywords = relationship("Keyword", secondary=keywords)
像其他 relationship()
参数,也接受一个字符串,按照中的定义传递表的字符串名称。 Base.metadata.tables
收藏:
class Author(Base):
__tablename__ = 'authors'
id = Column(Integer, primary_key=True)
keywords = relationship("Keyword", secondary="keywords")
与传统的映射一样,使用 Table
作为也映射到类的“secondary”参数,除非 relationship()
声明时使用 viewonly=True
. 否则,工作单元系统可能会尝试对基础表重复INSERT和DELETE语句。