[sqlalchemy] Event do not fire on m2m relation

2019-03-18 Thread Денис Ралко
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.


Re: [sqlalchemy] Event do not fire on m2m relation

2019-03-18 Thread Денис Ралко
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

2019-03-20 Thread Денис Ралко
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 =