【问题标题】:Relationships in SQLalchemySQLalchemy 中的关系
【发布时间】:2017-12-29 20:35:14
【问题描述】:

SQL Alchemy 可以很好地处理邻接结构,例如一个自引用表 node,其中外键 node.parent_id 与主键 node.id 相关。

我有一个不太传统的模型,其中一个节点有两个父节点(一个家谱数据库)。其中,node.mat_idnode.pat_id 分别与母节点和父节点相关。 SQL Alchemy 也可以这样做:

mother = db.relationship("Node", 
    foreign_keys = "Node.mat_id", remote_side="Node.id")
father = db.relationship("Node", 
    foreign_keys = "Node.pat_id", remote_side="Node.id")

(使用声明式)。

因此,获取节点的两个父节点是直截了当的。我的问题是使用此设置获取节点的 children。我找不到一种建立关系的方法,相当于:

offspring = db.relationship("Node", 
    foreign_keys = "Node.mat_id | Node.pat_id")

我所管理的最好的方法是分别声明 mat_offspring 和 pat_offspring 关系并创建一个返回适当的成员函数 offspring() 。它有效,但似乎不优雅。有没有更好更传统的方法?

【问题讨论】:

  • 我可以建议更改架构。为什么需要 mat_id 和 pat_id 分开?您可以使用两列:ID 和 sex_flag(布尔值)。这应该可以解决您的问题,因为您现在有 1 列可供参考。这对您的情况有适当的改变吗?
  • 这是一个预先存在的模式,被其他软件使用,因此改变它不太可能,至少在短期内是不可能的。你能稍微扩展一下你的建议吗?在未来的某个时候可能值得探索它。
  • 啊,我想我明白你的意思了:每个孩子有两个(parentid/childid)行的附加连接表?是的,我想这应该可行,如果我从这里开始,可能会是一个更好的设计。鉴于现有架构,我更喜欢一个解决方案,但感谢您的建议 - 我会支持它,但我是新来的,所以我似乎还没有权限这样做。

标签: python sqlalchemy relational


【解决方案1】:

鉴于原始架构的限制,您走在了正确的轨道上。而不是foreign_keys,您可以将连接条件作为primaryjoin 传递:

class Node(Base):
    __tablename__ = "node"

    id = Column(Integer, primary_key=True)
    mat_id = Column(ForeignKey(id))
    pat_id = Column(ForeignKey(id))

    mother = relationship("Node", foreign_keys=[mat_id], remote_side=id)
    father = relationship("Node", foreign_keys=[pat_id], remote_side=id)
    offspring = relationship("Node",
        primaryjoin=or_(id == mat_id, id == pat_id),
        viewonly=True)

请注意,由于连接条件更复杂,关系定义为view only。换句话说,您不能简单地通过它向节点添加后代,因为您无法确定父节点是新添加的后代的父亲还是母亲。从这个意义上说,你原来分开的母系和父系关系是优越的。

【讨论】:

  • 谢谢,我去看看。这个项目只不过是一个初步了解 Python 和 SQLAlchemy 的借口,几年前就被放弃了。正如您从另一个问题中知道的那样,尽管我现在已经开始为另一个项目再次研究它,所以该技术可能仍然有用。
猜你喜欢
  • 2013-10-22
  • 2013-05-01
  • 2014-10-19
  • 1970-01-01
  • 1970-01-01
  • 2013-11-03
  • 1970-01-01
  • 2019-12-06
  • 2023-03-17
相关资源
最近更新 更多