[英]How do I set up a adjacency list with an association object with SQLAlchemy?
我正在尝试创建一个数据库模型,您可以在其中拥有一堆产品,这些产品可能是其他产品的一部分,也包含其他产品。 我已经想出了如何做到这一点:
product_to_product = Table(
"product_to_product",
Base.metadata,
Column("id", Integer, primary_key=True),
Column("parent_id", Integer, ForeignKey("products.id")),
Column("child_id", Integer, ForeignKey("products.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, primary_key=True)
parents = relationship(
"Product",
secondary=ParentReference,
primaryjoin=id == ParentReference.child_id,
secondaryjoin=id == ParentReference.parent_id,
backref=backref("children"),
)
如果通过多对多关系链接在一起的对象是两个不同的对象(如User
和Community
),我发现了很多例子,但从来没有在这种情况下它是同一个对象。 我的尝试是从不同的例子拼凑起来的,但它不像以前那样与脚本一起工作。 我还看到过使用association_proxy
函数和其他几种方法的示例,但我无法使其正常工作。
我的目标是能够像以前一样添加产品、链接它们并导航它们,而且还能够从Product
访问ParentReference
对象,以便我可以获取关于它的附加数据。 有人可以帮我解决这个问题吗?
经过更多的反复试验,我想出了如何做到这一点。 这是我的解决方案:
class ParentReference(Base):
__tablename__ = "parent_references"
parent_id = Column(Integer, ForeignKey("products.id"), primary_key=True)
child_id = Column(Integer, ForeignKey("products.id"), 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]
它允许我访问父母/孩子,以及参考对象和其中的额外数据。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.