繁体   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