簡體   English   中英

如何使用 SQLAlchemy 設置具有關聯對象的鄰接列表?

[英]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"),
    )

如果通過多對多關系鏈接在一起的對象是兩個不同的對象(如UserCommunity ),我發現了很多例子,但從來沒有在這種情況下它是同一個對象。 我的嘗試是從不同的例子拼湊起來的,但它不像以前那樣與腳本一起工作。 我還看到過使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM