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.

Reply via email to