sqlalchemy:在父表和子表之间“同步” jsonb列

时间:2019-11-25 23:00:33

标签: python database postgresql sqlalchemy flask-sqlalchemy

假设我们有两个sqlalchemy类

from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.dialects.postgresql import JSONB


db = SQLAlchemy()

class Parent(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    data = db.Column(JSONB)

class Child(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    parent_id = db.Column(db.Integer, db.ForeignKey("parent.id"))
    parent = db.relationship(Parent, backref="children")
    data = db.Column(JSONB)

Child.data的内容是字典dParent.data的内容是字典列表,每个孩子一个,即parent.data = [child.data for child in parent.children]

是否可以使两个data列保持同步?


原则上,例如删除Parent.data列,并将其替换为仅返回[child.data for child in parent.children]的属性。但是,在我们的用例中,这非常慢,因此我们想在Parent.data列中保留聚合数据的副本。此外,应用程序的某些部分会立即修改整个Parent.data,而其他部分会修改Child.data。 我考虑过将data设为“私有”,并编写了一个自动更新另一个表中相应列的设置器(也许在更新之前检查它是否已更改,以避免最终陷入无限循环)。有更好的方法吗?

谢谢:)

1 个答案:

答案 0 :(得分:0)

您可能想使用事件监听器。取决于您的json的结构,类似下面的事情应该执行

import sqlalchemy as sa
@sa.event.listens_for(Parent.data, "modified")
def _parent_data_modified(parent, data, initiator):
    for child in parent.children:
        # adjust for your data structure
        child.data = data[child.id]

@sa.event.listens_for(Child.data, "modified")
def _child_data_modified(child, data, initiator):
    old_data = parent.data.copy()
    old_data[child.id] = data
    parent.data = old_data

https://docs.sqlalchemy.org/en/13/orm/extensions/mutable.html#receiving-events