Suppose we have two sqlalchemy classes
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)
The content of Child.data
is a dictionary d
and the content of Parent.data
is a list of dictionaries, one for each child, ie parent.data = [child.data for child in parent.children]
.
Is there a way to keep the two data
columns in sync?
In principle one could eg get rid of the Parent.data
column and replace it with a property that simply returns [child.data for child in parent.children]
. However, in our use case this is quite slow so we'd like to keep a copy of the aggregated data in the Parent.data
column. Moreover, some parts of the application modify the whole Parent.data
at once, while others modify Child.data
. I thought about making data
"private" and write a setter that automatically updates the corresponding column in the other table (maybe checking if it's changed before updating, in order to avoid ending up in an infinite loop). Is there a better way?
Thanks :)
You probably want to use event listeners. Something like the below should do it, depending on how your json is structured
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.