简体   繁体   English

自我参照多对多烧瓶SQLAlchemy

[英]self referential many to many flask-sqlalchemy

I for the life of me cannot figure out why this self-referential many-to-many will not be happy: 我一生无法弄清为什么这种自指的多对多会不高兴:

minor_contains = db.Table(
    'minor_contains',
    db.Column('parent_id', db.Integer, db.ForeignKey('minors.id'),
            primary_key=True),
    db.Column('contains_id', db.Integer, db.ForeignKey('minors.id'),
            primary_key=True))

class Minor(db.Model):
    __tablename__ = 'minors'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String())
    ...
    contains = db.relationship(
        "Minor",
        secondary=minor_contains,
        primaryjoin="id == minor_contains.c.parent_id",
        secondaryjoin="id == minor_contains.c.contains_id",
        backref="contained_by",
        lazy='dynamic')

I've tried reworking it a few different ways based on examples I've seen for SQLAlchemy and for Flask-SQLAlchemy, but I consistently end up where either I get the following error message or I end up in an infinite loop somewhere. 我已经尝试过根据针对SQLAlchemy和Flask-SQLAlchemy看到的示例以几种不同的方式对它进行重做,但是我始终会遇到以下错误消息,或者最终陷入无限循环。

E ArgumentError: Could not locate any simple equality expressions involving locally mapped foreign key columns for primary join condition 'minor_contains.parent_id = :parent_id_1' on relationship Minor.contains. E ArgumentError:无法在关系Minor.contains上找到涉及本地联接条件'minor_contains.parent_id =:parent_id_1'的涉及本地映射外键列的任何简单等式表达式。 Ensure that referencing columns are associated with a ForeignKey or ForeignKeyConstraint, or are annotated in the join condition with the foreign() annotation. 确保引用列与ForeignKey或ForeignKeyConstraint关联,或在联接条件中使用foreign()注释进行注释。 To allow comparison operators other than '==', the relationship can be marked as viewonly=True. 要允许除“ ==”以外的比较运算符,可以将该关系标记为viewonly = True。

UPDATE 更新

I'm really failing to understand the error message because it shows the column from the join table being compared to itself, where the condition on the join should be the PK of the minors table compared to the FK in the join table. 我真的无法理解该错误消息,因为它显示了连接表中的列与其自身进行比较,其中连接的条件应该是未成年人表的PK与连接表中的FK相比。

I'll also add a version of this that just hangs forever. 我还将添加一个永久挂起的版本。 You'll see I've been reworking variable names and such just rewriting it over and over hoping if I take a fresh stab at it, I'll somehow be smarter the second or fifth time around. 您会看到我一直在修改变量名,这样就一遍又一遍地重写它,希望如果我重新尝试一下它,那么第二或第五次我会变得更聪明。

minor_contains = db.Table(
    'minor_contains',
    db.Column('parent_minor_id', db.Integer, db.ForeignKey('minors.id'),
            primary_key=True),
    db.Column('contains_minor_id', db.Integer, db.ForeignKey('minors.id'),
            primary_key=True))

class Minor(db.Model):
    __tablename__ = 'minors'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String())
    ...
    contains = db.relationship(
        "Minor",
        secondary=minor_contains,
        primaryjoin=id==minor_contains.c.parent_minor_id,
        secondaryjoin=id==minor_contains.c.contains_minor_id,
        backref=db.backref("minor_contains", lazy='dynamic'))

I think it's necessary to specify the model name in the join conditions. 我认为有必要在连接条件中指定模型名称。

contains = db.relationship(
    "Minor",
    secondary=minor_contains,
    primaryjoin="Minor.id == minor_contains.c.parent_id",
    secondaryjoin="Minor.id == minor_contains.c.contains_id",
    backref=db.backref('minor_contains', lazy='dynamic'),
    lazy='dynamic')

I had the same issue and it fixed the problem. 我有同样的问题,它解决了这个问题。 I found a useful answer here : link 我在这里找到了一个有用的答案: 链接

Have you tried doing this? 您是否尝试过这样做?

minor_contains = db.Table(
    'minor_contains',
    db.Column('parent_id', db.Integer, db.ForeignKey('minors.id'),
        primary_key=True),
    db.Column('contains_id', db.Integer, db.ForeignKey('minors.id'),
        primary_key=True))

class Minor(db.Model):
    __tablename__ = 'minors'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String())
    ...
    contains = db.relationship(
        "Minor",
        secondary=minor_contains,
        primaryjoin="id == minor_contains.c.parent_id",
        secondaryjoin="id == minor_contains.c.contains_id",
        backref=db.backref('minor_contains', lazy='dynamic'),
        lazy='dynamic')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM