簡體   English   中英

如何在SQLAlchemy中以聲明方式建立具有遞歸外鍵和關系的表?

[英]How to set up a table with a recursive foreign key and a relationship declaratively in SQLAlchemy?

假設我有一個存儲節點樹的表“節點”。 每個節點都有一個主鍵id和一列parent_id。 當然,我想訪問每個節點實例的父級屬性,即一個關系。 一個可以嘗試:

import sqlalchemy, sqlalchemy.orm, sqlalchemy.ext.declarative
engine = sqlalchemy.create_engine('sqlite:///PATHTOMYDATABASE', echo=True)
Base = sqlalchemy.ext.declarative.declarative_base()
class Node(Base):
    __tablename__ = "nodes"
    id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True) 
    parent_id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("nodes.id"))
    parent = sqlalchemy.orm.relationship("Node", backref=sqlalchemy.orm.backref("childs"))
Base.metadata.create_all(engine)

但是當我這樣做時,我得到一個錯誤:

sqlalchemy.exc.InvalidRequestError: Table 'nodes' is already defined for this MetaData instance. Specify 'useexisting=True' to redefine options and columns on an existing Table object.

我不知道在什么時候可以將該選項設置為'useexisting=True' 這是正確的方法嗎?

編輯:實際上,該錯誤間接來自原始腳本的另一部分。 如果用臨時數據庫:memory:代替數據庫路徑,則它可以正常工作。 感謝TokenMacGuy。

因此,以上示例可以視為一個工作示例。

由於某種原因,您已經為該表注冊了一個類,或者已兩次(可能是間接地)定義了該表。 在python命令行上進行實驗時,這種情況最常見。 sqlalchemy記住表定義和類映射的時間長於立即顯而易見的時間(從實際MetaData實例的生命周期開始)。 確保只定義一次表(如果在其中,則退出python解釋器並重新啟動它)。 它們可能已經存在的其他原因是由於表反射,或者是在沒有真正清除sys.modules情況下調用了reload()

如果使用表反射,則將useexisting=True選項傳遞給__table_args__類變量中的聲明性擴展:

class Node(Base):
    __tablename__ = "nodes"
    __table_args__ = {"useexisting": True}

但是只有在確保在定義python類之前故意定義表時才這樣做。

如果這些方法都不能解決問題,請將模塊縮小為一個顯示問題的最小示例,然后將整個內容發布在您的答案中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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