簡體   English   中英

SQLAlchemy 用戶多對多關系

[英]SQLAlchemy User Many to Many Relationship

我正在研究一個用戶結構,其中用戶可以擁有由用戶對象組成的父母和孩子。 我一直在嘗試讓以下內容在 SQLAlchemy 和 Flask 中以多種不同的方式工作。

這是我要如何構建它的示例:

UserTable
id | name
---+-----
1  | Kim
2  | Tammy
3  | John
4  | Casey
5  | Kyle

UserRelationship
id | parent_user_id | child_user_id
---+----------------+---------------
1  | 1              | 2
2  | 1              | 3
3  | 4              | 2

Kim 是 Tammy 和 John 的父母。 凱西是塔米的父母。 塔米是金和凱西的孩子。 約翰是金的孩子。 凱爾沒有孩子也沒有父母。


我的錯誤是:

sqlalchemy.exc.AmbiguousForeignKeysError: Could not determine join condition 
between parent/child tables on relationship User.parents - there are multiple 
foreign key paths linking the tables via secondary table 'user_relationship'. 
Specify the 'foreign_keys' argument, providing a list of those columns which 
should be counted as containing a foreign key reference from the secondary 
table to each of the parent and child tables.

我的model.py文件如下所示:

user_relationship = db.Table(
    'user_relationship',
    db.Model.metadata,
    db.Column('child_user_id', db.Integer, db.ForeignKey('user.id')),
    db.Column('parent_user_id', db.Integer, db.ForeignKey('user.id'))
)

class User(db.Model):
    __tablename__ = 'user'

    id = db.Column(db.Integer, primary_key=True, unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True)
    pwdhash = db.Column(db.String(54))

    parents = relationship('User',
        secondary=user_relationship,
        backref=db.backref('children'),
        cascade="all,delete")

這可能不是處理 Flask 或 SQLAlchemy 中多對多分層用戶關系的最佳方式。任何關於如何構建它的見解都會很棒。

謝謝

db.Table主要用於兩個不同實體之間存在Many to Many關系時。 這里父母和孩子都是User

就您而言,下面的代碼會很好:

class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True, unique=True,     nullable=False)
    email = db.Column(db.String(120), unique=True)
    pwdhash = db.Column(db.String(54))


class Parent(db.Model):
    __tablename__ = 'parents'
    child_id = db.Column(db.Integer, db.Foreignkey('users.id'))
    parent_id = db.Column(db.Integer, db.Foreignkey('users.id'))
    child = db.relationship('User', foreign_keys=[child_id], backref = 'parents')

flask_sqlalchemy寫在上面SQLAlchemy ,有這個問題的一個很好的闡述在這里 (處理多個連接路徑)在SQLAlchemy的網站。

使用primaryjoinsecondaryjoin參數。

最近我遇到了類似的問題,雖然我看到文檔和接受的答案建議用戶Parent model 而不是創建關系表,但我創建一個單獨的 model 來存儲關系是沒有意義的,因為我的所有模型都繼承自BaseModel和我不希望這種關系獲得BaseModel的附加功能。 主要是因為我的BaseModel默認有idBaseTable沒有包含id

所以,我更喜歡為關系創建一個單獨的 Sqlalchemy 表,而不是 Model。

要完成它,您可以使用primaryjoinsecondaryjoin arguments,如下所示。 我與 relationship_manager 之間存在多對一的投資者關系。 要使其成為多對多,您可以從關系表中的investor_id中刪除unique=True ,並從用戶 model 中的 relationship_manager 中刪除uselist=False

# user.py 
from database.relationships.relationship_managers import relationship_managers

class User(BaseModel):
    id = Column(Integer, primary_key=True)
    relationship_manager = relationship(
        "User",
        secondary=relationship_managers,
        uselist=False,
        primaryjoin=("relationship_managers.c.investor_id == User.id"),
        secondaryjoin=("relationship_managers.c.rel_manager_id == User.id"),
        backref="investors"
    )
# relationship_managers.py
relationship_managers = BaseTable(
    "relationship_managers",
    Column("investor_id", Integer, ForeignKey('user.id', ondelete="CASCADE"), unique=True),
    Column("rel_manager_id", Integer, ForeignKey('user.id', ondelete="CASCADE")),
)

在這里, primaryjoin執行第一次與 investor_id 的連接並獲取記錄用戶記錄,但這對我們來說還不夠。 所以,我們需要secondaryjoin專門獲取 relationship_manager 的 id。

如有任何疑問,請隨時發表評論並提出建議。 希望這可以幫助使用 Sqlalchemy 在其項目中同時擁有模型和表格的任何人。:)

暫無
暫無

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

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