【问题标题】:Specify join condition in SQLalchemy ORM without foreign key在没有外键的 SQLalchemy ORM 中指定连接条件
【发布时间】:2016-07-12 13:15:03
【问题描述】:

我在 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')

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

【问题讨论】:

  • 投反对票的人,你能解释一下我的问题是什么问题吗?

标签: python mysql sqlalchemy alembic


【解决方案1】:

要使relationship 工作,您可以指定显式连接条件:

parent = relationship(Parent, primaryjoin=parent_metadata_id == Parent.metadata_id)

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

session.query(Child).join(Child.parent)

或者,明确指定连接条件:

session.query(Child).join(Child, Child.parent_metadata_id == Parent.metadata_id)

对 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

【讨论】:

  • 一旦我将 info 参数放在 ForeignKey( ... ) 之外,这对我有用。我编辑了您的答案以反映这一点。感谢您的帮助!
  • @Eli 这使得 alembic 完全跳过了该列。也许您使用的是旧版本的 alembic(在 0.7.1 之前它不支持 include_object 中的外键)?
  • 你是对的。我现在在 Alembic 0.8.5 上,我可以将 info 放在 ForeignKey( ... ) 中,但现在它只是被忽略了。虽然放在列中时它工作正常,但正如你所说,整个列被忽略。
猜你喜欢
  • 2015-03-10
  • 2011-09-15
  • 1970-01-01
  • 2023-01-14
  • 2015-08-27
  • 2013-07-16
  • 2011-09-08
  • 2012-05-15
  • 1970-01-01
相关资源
最近更新 更多