Sorry, my mistake Site.entity_id == MODEL_2.id And I solve my problem by change mapper.attrs -> mapper.column_attrs
And now I want to ask you Can event directly set on Table colums? On Monday, March 18, 2019 at 10:28:54 PM UTC+2, Mike Bayer wrote: > > On Mon, Mar 18, 2019 at 11:07 AM Денис Ралко <ral...@gmail.com > <javascript:>> 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+...@googlegroups.com <javascript:>. > > To post to this group, send email to sqlal...@googlegroups.com > <javascript:>. > > 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.