配置关系¶

参见

本节描述有关声明性系统如何与SQLAlchemy ORM关系构造交互的具体信息。有关设置映射之间关系的常规信息,请参见 对象关系教程基本关系模式 .

与其他类的关系是以通常的方式完成的,其中添加了类指定给 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.Addressmyapp.model.lookup.Address ,我们可以指定 address.Addresslookup.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语句。