提交后Flask-SQLAlchemy多对多邻接列表更改

时间:2016-01-22 11:30:27

标签: python flask sqlalchemy flask-sqlalchemy adjacency-list

我有一个与自身有多对多关系的模型:另一个操作或其自身可以阻止操作。

operation_to_operation_association_table = db.Table(
    "preventing_operations",
    db.Column("id", db.Integer, primary_key=True),
    db.Column("preventing_operation_id", db.Integer, db.ForeignKey("operation.id")),
    db.Column("prevents_operation_id", db.Integer, db.ForeignKey("operation.id")))



class Operation(BaseModel): # BaseModel defines id and creation/update times
    name = db.Column(db.String)

    bodypart_id = db.Column(db.Integer, db.ForeignKey(BodyPart.id))
    bodypart = db.relationship("BodyPart", backref="operations")

    prevents = db.relationship("Operation", secondary=operation_to_operation_association_table,
                               foreign_keys=[operation_to_operation_association_table.c.preventing_operation_id],
                               backref="prevented_by")


    def __eq__(self, other):
        return other and self.name == other.name and self.bodypart == other.bodypart

然后在shell中,从一个新的数据库:

In [1]: bp = BodyPart(name="liver")

In [2]: db.session.add(bp)

In [3]: db.session.commit()

In [4]: o1, o2 = Operation(name="viewing", bodypart=bp), Operation(name="removing", bodypart=bp)

In [5]: db.session.add_all([o1, o2])

In [6]: db.session.commit()

In [7]: o1, o2
Out[7]: (Viewing the liver (1), Removing the liver (2))

In [8]: o1.prevents, o2.prevents
Out[8]: ([], [])

In [9]: o2.prevents.append(o1)

In [10]: o1.prevents, o2.prevents
Out[10]: ([], [Viewing the liver (1)])

In [11]: db.session.commit()

In [12]: o1.prevents, o2.prevents
Out[12]: ([Viewing the liver (1)], [])

提交切换列表?!

记录查询,插入查询SQLAlchemy发送数据库似乎是错误的:

INSERT INTO preventing_operations (prevents_operation_id) VALUES (?)
with values (1,)

应该是:

INSERT INTO preventing_operations (prevents_operation_id, preventing_operation_id) VALUES (?)
with values (2, 1)

我在这里做错了什么?我错误地定义了我的关系吗?那为什么它只会在我提交时改变?

1 个答案:

答案 0 :(得分:1)

问题在于foreign_keys设置,我实际上不确定究竟需要对foreign_keys做什么。

但我建议改用primaryjoinsecondaryjoin。这样设置对我来说更明显(并且有效):

prevents = relationship(
    "Operation",
    secondary=operation_to_operation,
    primaryjoin=id == operation_to_operation.c.preventing_operation_id,
    secondaryjoin=id == operation_to_operation.c.prevents_operation_id,
    backref="prevented_by")

以下是the working examplemodule with base model

运行示例如下: - 下载两个文件,保存到同一个文件夹(或克隆回购) - 运行`python many_many_save_issue.py。

我用SQLAlchemy == 1.0.6测试了它。