如何在SQLAlchemy中将属性比较编译为SQL表达式?

yol*_*eem 5 python orm sqlalchemy

有两个表,表A的一列指向另一个表B的主键.

但是它们被放在不同的数据库中,所以我无法用外键配置它们.

配置via relationship()不可用,所以我手动实现了属性属性.

class User(Base):
    __tablename__ = 'users'
    id = Column(BigInteger, id_seq, primary=True)
    name = Column(Unicode(256))


class Article(Base):
    __tablename__ = 'articles'
    __bind_key__ = 'another_engine'
    # I am using custom session configures bind
    # each mappers to multiple database engines via this attribute.

    id = Column(BigInteger, id_seq, primary=True)
    author_id = Column(BigInteger, nullable=False, index=True)
    body = Column(UnicodeText, nullable=False)

    @property
    def author(self):
        _session = object_session(self)
        return _session.query(User).get(self.author_id)

    @author.setter
    def author(self, user):
        if not isinstance(user, User):
            raise TypeError('user must be a instance of User')
        self.author_id = user.id
Run Code Online (Sandbox Code Playgroud)

此代码适用于简单操作.但它导致脏查询使SQLAlchemy的功能毫无意义.

如果通过relationship()(例如query.filter(author=me))搞砸(例如query.filter(author_id=me.id))来配置代码将是简单的.

关系(例如,连接)相关的功能永远不能用于查询构建.

我是否可以在构建查询条件(filter()/filter_by())时使用属性属性?

zzz*_*eek 1

您仍然可以在这里使用关系。如果你坚持“延迟加载”,它会在加载数据库 A 中的主导项后,在数据库 B 中查询相关项。你可以在列中放置一个foreignkey()指令,即使在列中没有真正的指令。数据库。或者你可以直接使用primaryjoin:

class User(Base):
    __tablename__ = 'users'
    id = Column(BigInteger, id_seq, primary=True)
    name = Column(Unicode(256))


class Article(Base):
    __tablename__ = 'articles'
    __bind_key__ = 'another_engine'

    id = Column(BigInteger, id_seq, primary=True)
    author_id = Column(BigInteger, nullable=False, index=True)
    body = Column(UnicodeText, nullable=False)

    author = relationship("User", 
                primaryjoin="foreign(Article.author_id) == User.id")
Run Code Online (Sandbox Code Playgroud)