在没有外键的SQLalchemy ORM中指定连接条件

Eli*_*Eli 1 python mysql sqlalchemy alembic

我在SQLAlchemy中有两个模型,这些模型已自动加入外键,如下所示:

class Parent(Base):
    __tablename__ = 'parents'

    id = Column(Integer, primary_key=True)
    name = Column(String(300), nullable=False)
    metadata_id = Column(Integer, nullable=True, index=True)

class Child(Base):
    __tablename__ = 'children'

    id = Column(Integer, primary_key=True)
    name = Column(String(300), nullable=False)
    parent_metadata_id = \
        Column(ForeignKey('parents.metadata_id'),
               nullable=True, primary_key=True)
    parent = relationship(u'Parent')
Run Code Online (Sandbox Code Playgroud)

这个工作很好,我可以很容易地从孩子的父母那里得到帮助。现在,由于超出了此问题范围的技术原因,我不得不摆脱数据库中的外键。我试图在SQLAlchemy中解决该问题,但是没有任何替换代码(使用primaryjoins或backrefs)起作用。我在这里看到了另一个答案,只是说这是对SQLAlchemy的谎言,并告诉我我具有外键关系,但这使Alembic尝试在我自动生成的每个新修订版本上创建外键关系,这确实很烦人。什么是正确的方法?

uni*_*rio 5

要进行relationship工作,您可以指定显式联接条件:

parent = relationship(Parent, primaryjoin=parent_metadata_id == Parent.metadata_id)
Run Code Online (Sandbox Code Playgroud)

要使联接Child起作用,可以指定关系而不是实体:

session.query(Child).join(Child.parent)
Run Code Online (Sandbox Code Playgroud)

或者,显式指定连接条件:

session.query(Child).join(Child, Child.parent_metadata_id == Parent.metadata_id)
Run Code Online (Sandbox Code Playgroud)

说谎也可以使用SQLAlchemy。您可以通过指定include_object参数使Alembic忽略外键:

class Child(Base):
    ...
    parent_metadata_id = Column(ForeignKey( ... ), info={"skip_autogenerate": True}, ...)

def include_object(object, name, type_, reflected, compare_to):
    if not reflected and object.info.get("skip_autogenerate", False):
        return False
    return True
Run Code Online (Sandbox Code Playgroud)