Re: [sqlalchemy] Event do not fire on m2m relation
On Wed, Mar 20, 2019 at 7:54 AM Денис Ралко wrote: > > 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? events for changes of value need to be set for ORM level attributes. If you can illustrate what you mean that might help. > > On Monday, March 18, 2019 at 10:28:54 PM UTC+2, Mike Bayer wrote: >> >> On Mon, Mar 18, 2019 at 11:07 AM Денис Ралко 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,
Re: [sqlalchemy] Event do not fire on m2m relation
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 Денис Ралко > 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 Денис Ралко wrote: > >> > > >> > Hi, I have some issue > >> > > >> > I try implement track logic > >> > I have 2 Models and connecting Table > >> > > >> > My first class > >> > > >> >
Re: [sqlalchemy] Event do not fire on m2m relation
On Mon, Mar 18, 2019 at 11:07 AM Денис Ралко 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 Денис Ралко 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, >> > >> >
Re: [sqlalchemy] Event do not fire on m2m relation
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) 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 Денис Ралко > 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.
Re: [sqlalchemy] Event do not fire on m2m relation
On Mon, Mar 18, 2019 at 10:30 AM Денис Ралко 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+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.
[sqlalchemy] Event do not fire on m2m relation
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 ? 2. if i set before_flush event and change some in MODEL_1, event fire, but session have no modified objects -- 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.