On Mon, Mar 18, 2019 at 11:07 AM Денис Ралко <ralk...@gmail.com> wrote: > > Thx for your quick answer. > About second question > > I have event, for example > > def track_instances_before_flush(session, context, instances): > for obj in chain(session.new, session.dirty): > if session.is_modified(obj): > print "Before Flush" > > table_name = obj.__class__.__dict__['__tablename__'] > > print "Table_name ---", table_name > > > print "Raw obj - ", obj > > state_before = {} > state_after = {} > mapper = inspect(obj) > attrs = class_mapper(obj.__class__).column_attrs > > for attr in attrs: > hist = mapper.attrs[attr.key].history > if hist.has_changes(): > state_before[attr.key] = get_history(obj, attr.key)[2][0] > state_after[attr.key] = getattr(obj, attr.key) > > print "BEFORE -", state_before > print "AFTER -", state_after > > > > and register it by > > listen(app.db.session, 'before_flush', track_instances_before_flush)
the code you've sent is still incomplete, for example i dont know what "Site" is, but if you want to track relationships you need to look at mapper.attrs or mapper.relationship_attrs. POC below with what I could derive from your code fragments. from __future__ import print_function from itertools import chain from sqlalchemy import Column from sqlalchemy import create_engine from sqlalchemy import ForeignKey from sqlalchemy import inspect from sqlalchemy import Integer from sqlalchemy import Table from sqlalchemy import UniqueConstraint from sqlalchemy.event import listen from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import class_mapper from sqlalchemy.orm import relationship from sqlalchemy.orm import Session Base = declarative_base() class MODEL_1(Base): __tablename__ = "MODEL_1" entity_id = Column(Integer, primary_key=True) # Don't know what "Site" is # attr_1 = relationship( # "MODEL_2", # secondary="test2test", # lazy="dynamic", # primaryjoin="MODEL_1.id == test2test.c.first_id", # secondaryjoin="test2test.c.second_id == Site.entity_id", # ) class MODEL_2(Base): __tablename__ = "MODEL_2" id = Column(Integer, primary_key=True) attr_2 = relationship("MODEL_1", secondary="test2test", lazy="dynamic") t_ = Table( "test2test", Base.metadata, Column( "first_id", Integer, ForeignKey("MODEL_1.entity_id"), nullable=False ), Column("second_id", Integer, ForeignKey("MODEL_2.id"), nullable=False), UniqueConstraint("first_id", "second_id", name="uq_test2test"), ) def track_instances_before_flush(session, context, instances): for obj in chain(session.new, session.dirty): if session.is_modified(obj): print("Before Flush") table_name = obj.__class__.__dict__["__tablename__"] print("Table_name ---", table_name) print("Raw obj - ", obj) state_before = {} state_after = {} mapper = inspect(obj) attrs = class_mapper(obj.__class__).attrs for attr in attrs: hist = mapper.attrs[attr.key].history if hist.has_changes(): state_before[attr.key] = hist[2] or hist[1] state_after[attr.key] = hist[0] print("BEFORE -", state_before) print("AFTER -", state_after) e = create_engine("sqlite://", echo=True) Base.metadata.create_all(e) s = Session(e) listen(s, "before_flush", track_instances_before_flush) m1 = MODEL_1() m2 = MODEL_2() s.add_all([m1, m2]) s.commit() print("------------------") m2.attr_2.append(m1) s.commit() > > > and in output i see > Before Flush > Table_name --- MODEL_1 > Raw obj - <'MODEL_1' id=2050> > > BEFORE - {} > AFTER - {} > > In view I change only attr_1 for MODEL_1 > > On Monday, March 18, 2019 at 4:48:00 PM UTC+2, Mike Bayer wrote: >> >> On Mon, Mar 18, 2019 at 10:30 AM Денис Ралко <ral...@gmail.com> wrote: >> > >> > Hi, I have some issue >> > >> > I try implement track logic >> > I have 2 Models and connecting Table >> > >> > My first class >> > >> > class MODEL_1(object): >> > # some values >> > >> > # relations: >> > attr_1 = db.relationship('MODEL_2', >> > secondary="test2test", >> > lazy='dynamic', >> > primaryjoin="MODEL_1.id == >> > test2test.c.first_id", >> > secondaryjoin='test2test.c.second_id == >> > Site.entity_id') >> > >> > Second class >> > >> > class MODEL_2(object): >> > # some values >> > attr_2 = db.relationship('MODEL_1', secondary='test2test', >> > lazy='dynamic') >> > >> > >> > And relation table >> > >> > >> > t_ = db.Table( >> > 'test2test', >> > db.Model.metadata, >> > >> > db.Column('first_id', db.Integer, >> > db.ForeignKey('MODEL_1.entity_id'), >> > nullable=False), >> > db.Column('second_id', db.Integer, >> > db.ForeignKey('MODEL_2.id'), >> > nullable=False), >> > db.UniqueConstraint('first_id', 'second_id', name='uq_test2test') >> > ) >> > >> > >> > I have some questions >> > >> > 1. can i do some table event what will fire, when will change some values >> > in t_ table ? >> >> via the relationship, sure, use @validates or AttributeEvents for >> MODEL_1.attr1, MODEL_2.attr2 >> >> https://docs.sqlalchemy.org/en/latest/orm/events.html?highlight=attributeevents#sqlalchemy.orm.events.AttributeEvents >> >> >> > >> > 2. if i set before_flush event and change some in MODEL_1, event fire, but >> > session have no modified objects >> >> you would need to send along a complete example illustrating what you're >> doing. >> >> >> >> > >> > -- >> > SQLAlchemy - >> > The Python SQL Toolkit and Object Relational Mapper >> > >> > http://www.sqlalchemy.org/ >> > >> > To post example code, please provide an MCVE: Minimal, Complete, and >> > Verifiable Example. See http://stackoverflow.com/help/mcve for a full >> > description. >> > --- >> > You received this message because you are subscribed to the Google Groups >> > "sqlalchemy" group. >> > To unsubscribe from this group and stop receiving emails from it, send an >> > email to sqlalchemy+...@googlegroups.com. >> > To post to this group, send email to sqlal...@googlegroups.com. >> > Visit this group at https://groups.google.com/group/sqlalchemy. >> > For more options, visit https://groups.google.com/d/optout. > > -- > SQLAlchemy - > The Python SQL Toolkit and Object Relational Mapper > > http://www.sqlalchemy.org/ > > To post example code, please provide an MCVE: Minimal, Complete, and > Verifiable Example. See http://stackoverflow.com/help/mcve for a full > description. > --- > You received this message because you are subscribed to the Google Groups > "sqlalchemy" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to sqlalchemy+unsubscr...@googlegroups.com. > To post to this group, send email to sqlalchemy@googlegroups.com. > Visit this group at https://groups.google.com/group/sqlalchemy. > For more options, visit https://groups.google.com/d/optout. -- SQLAlchemy - The Python SQL Toolkit and Object Relational Mapper http://www.sqlalchemy.org/ To post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See http://stackoverflow.com/help/mcve for a full description. --- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at https://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.