如何使用SQLAlchemy与关联对象建立邻接表?

问题描述

我正在尝试创建一个数据库模型,在这里您可以拥有一堆可以属于其他产品并且也包含其他产品的产品。我已经知道如何做到这一点:

factors.Add(potentialFactor);

这使我可以添加以下产品:

product_to_product = Table(
    "product_to_product",Base.Metadata,Column("id",Integer,primary_key=True),Column("parent_id",ForeignKey("products.id")),Column("child_id",)


class Product(Base):
    __tablename__ = "products"

    id = Column(Integer,primary_key=True)

    parents = relationship(
        "Product",secondary=product_to_product,primaryjoin=id == product_to_product.c.parent_id,secondaryjoin=id == product_to_product.c.child_id,backref="children",)

然后我可以获取所有产品,并且父母/孩子之间的链接可以完全按照我的意愿工作。

现在,我想转而使用关联对象来管理链接,因为我想拥有其他数据。我尝试过这样设置:

root = Product()

parent1 = Product()
parent2 = Product()

child1 = Product()
child2 = Product()
child3 = Product()

root.children = [parent1,parent2]
parent1.children = [child1,child2,child3]
parent2.children = [child1,child2]

我发现有很多示例,如果通过多对多关系链接在一起的对象是两个不同的对象(例如class ParentReference(Base): __tablename__ = "parent_references" id = Column(Integer,primary_key=True) parent_id = Column(Integer,ForeignKey("products.id")) child_id = Column(Integer,ForeignKey("products.id")) additional_data = Column(String) class Product(Base): __tablename__ = "products" id = Column(Integer,secondary=ParentReference,primaryjoin=id == ParentReference.child_id,secondaryjoin=id == ParentReference.parent_id,backref=backref("children"),) User),但是在这种情况下永远不会同一对象。我的尝试是从不同的示例中总结出来的,但是它不能像以前那样与脚本一起工作。我还看到了使用Community函数和其他几种方法的示例,但我无法使其正常工作。

我的目标是能够像以前一样添加产品,链接产品并进行导航,还能够从association_proxy访问ParentReference对象,以便我可以获取其他数据在上面。有人可以帮我解决这个问题吗?

解决方法

经过更多的尝试和错误之后,我弄清楚了如何执行此操作。这是我的解决方案:

class ParentReference(Base):
    __tablename__ = "parent_references"

    parent_id = Column(Integer,ForeignKey("products.id"),primary_key=True)
    child_id = Column(Integer,primary_key=True)
    extra_data = Column(String)

    parent = relationship(
        "Product",primaryjoin=lambda: ParentReference.child_id == Product.id,backref="child_references"
    )
    child = relationship(
        "Product",primaryjoin=lambda: ParentReference.parent_id == Product.id,backref="parent_references"
    )


class Product(Base):
    __tablename__ = "products"

    id = Column(Integer,primary_key=True)

    parents = relationship(
        "Product",secondary="parent_references",primaryjoin=lambda: Product.id == ParentReference.parent_id,secondaryjoin=lambda: Product.id == ParentReference.child_id,backref="children"
    )

这是这样的:

root = Product()
parent1 = Product()
parent2 = Product()
child1 = Product()
child2 = Product()
child3 = Product()

parent1.parent_references = [
    ParentReference(parent=root,child=parent1,extra_data="Hello World!")
]
root.children.append(parent2)
parent1.children = [child1,child2,child3]
parent2.children = [child1,child2]

它使我可以访问父母/子女以及参考对象和其中的额外数据。