Re: [sqlalchemy] Modification tracking
> In an application, I have rather elaborate needs to track changes. > Now I need to track all modifications to all fields, including the > relationship list objects. One way to accomplish this would be within the database server itself. With a rule that, instead of updating a record, inserts a new one (and updates a "version" column). Sincerely, Wolfgang -- 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 http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/groups/opt_out.
Re: [sqlalchemy] Modification tracking
On Aug 22, 2013, at 5:58 PM, Hans-Peter Jansen wrote: > Dear Michael, > > > Hmm, it looks like that needs to be applied on every column attribute.. > >> you can get a list of all attributes mapped using mapper.attrs: >> http://docs.sqlalchemy.org/en/rel_0_8/orm/mapper_config.html?highlight=mapp >> er.attrs#sqlalchemy.orm.mapper.Mapper.attrs > > from here. Since I need to track all 'net' changes, that's rather unpractical. if you're just looking for "dirty" you can look at session.dirty itself, such as in a before_flush() handlernot sure what the specific scenario is. > That is: just change instance attributes in place, and check for dirtiness > later on, with session.is_modified(obj, passive = True). I've chosen this > interface, because the fact of *really* being modified is essential here. > > This scheme would do just fine, but doesn't work as expected. > > See attached code. Depending on modification state of parent (line 51), the > modification state of the child is detected (parent changed) or not (parent > unchanged). it looks like this code makes a change to p.children[0].name, and then expects that session.is_modified(p) would be True.is_modified() is per-object, so modifying Child means that just Child is modified, Parent hasn't changed at all. If you want to make an "is_modified()" that recurses through object graphs, you'd need to traverse down yourself through related attributes. I can show you what that looks like if this is what you want. > In my real code, it's the other way around, modifications to relations are > detected (as I iterate through all of them), but changes to the "parent" > aren't, although the correct SQL UPDATE code is executed after commit(). > Since > it isn't detected correctly, my app falls flat on its nose.. well if you change Child.name, the only UPDATE needed is on the "child" table. the "parent" table doesn't require an UPDATE in this case which is why session.is_modified() returns False. signature.asc Description: Message signed with OpenPGP using GPGMail
Re: [sqlalchemy] Modification tracking
On Donnerstag, 22. August 2013 23:58:17 Hans-Peter Jansen wrote: > Dear Michael, > Pardon, I'm using 0.8.2 ATM. > > Cheers, > Pete -- 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 http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/groups/opt_out.
Re: [sqlalchemy] Modification tracking
Dear Michael, thanks for the detailed response. On Mittwoch, 21. August 2013 16:55:18 Michael Bayer wrote: > On Aug 21, 2013, at 12:40 PM, Hans-Peter Jansen wrote: > > Hi, > > > > being new to SQLAlchemy, I try to get my way through it. > > > > In an application, I have rather elaborate needs to track changes. > > > > I've defined 3 classes with declarative, where the main class has > > relationships with two auxiliary classes, that refer to the main class > > with foreign references. All pretty basic stuff. > > > > Now I need to track all modifications to all fields, including the > > relationship list objects. > > > > What is the best way to accomplish this task with SQLAlchemy? > > > > Is there some boilerplate available to support this, or do I have to carry > > around two objects and compare them item by item? > you can intercept changes on attributes using the attribute event system: > http://docs.sqlalchemy.org/en/rel_0_8/orm/events.html#attribute-events > > otherwise you can get at the changes on an attribute after the fact (but > before a flush) using the history interface: > http://docs.sqlalchemy.org/en/rel_0_8/orm/session.html?highlight=history#sq > lalchemy.orm.attributes.History Hmm, it looks like that needs to be applied on every column attribute.. > you can get a list of all attributes mapped using mapper.attrs: > http://docs.sqlalchemy.org/en/rel_0_8/orm/mapper_config.html?highlight=mapp > er.attrs#sqlalchemy.orm.mapper.Mapper.attrs from here. Since I need to track all 'net' changes, that's rather unpractical. I've changed my code to cope with best practices hopefully (from what I can extract from the overwhelming docs). That is: just change instance attributes in place, and check for dirtiness later on, with session.is_modified(obj, passive = True). I've chosen this interface, because the fact of *really* being modified is essential here. This scheme would do just fine, but doesn't work as expected. See attached code. Depending on modification state of parent (line 51), the modification state of the child is detected (parent changed) or not (parent unchanged). In my real code, it's the other way around, modifications to relations are detected (as I iterate through all of them), but changes to the "parent" aren't, although the correct SQL UPDATE code is executed after commit(). Since it isn't detected correctly, my app falls flat on its nose.. Do you have any idea on this one? Cheers, Pete -- 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 http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/groups/opt_out. from sqlalchemy import Column, Integer, String, ForeignKey, create_engine from sqlalchemy.orm import relationship, backref, sessionmaker from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() ERR = 1 class Parent(Base): __tablename__ = 'parent' id = Column(Integer, primary_key=True) name = Column(String(100), nullable = False, index = True) children = relationship('Child', backref = 'parent', single_parent = True, # lazy = 'joined', cascade = 'all, delete-orphan') def __repr__(self): cl = [repr(c) for c in self.children] return 'Parent(%r, children: %s)' % (self.name, ', '.join(cl)) class Child(Base): __tablename__ = 'child' id = Column(Integer, primary_key=True) name = Column(String(100), nullable = False, index = True) parent_id = Column(Integer, ForeignKey('parent.id'), nullable = False) def __repr__(self): return 'Child(%r)' % (self.name) if __name__ == '__main__': engine = create_engine('sqlite://', echo = True) Base.metadata.create_all(engine) session = sessionmaker(engine, expire_on_commit=False)() def pr(obj, exp, msg): res = session.is_modified(obj, passive = True) print msg + ',', 'expected: %s,' % exp, 'outcome: %s,' % res, exp == res and 'okay' or 'FAILED' p = Parent(name = 'pa') c1 = Child(name = 'li') p.children.append(c1) print 'Starting with:', p session.add(p) session.commit() pr(p, False, 'initial session committed') if ERR: pr(p, False, 'parent not renamed') else: p.name = 'po' pr(p, True, 'parent renamed to "po"') c1.name = 'lo' pr(c1, True, 'child renamed to "lo", testing child') pr(p, True, 'child renamed to "lo", testing parent') session.commit()
Re: [sqlalchemy] Modification tracking
On Aug 21, 2013, at 12:40 PM, Hans-Peter Jansen wrote: > Hi, > > being new to SQLAlchemy, I try to get my way through it. > > In an application, I have rather elaborate needs to track changes. > > I've defined 3 classes with declarative, where the main class has > relationships with two auxiliary classes, that refer to the main class with > foreign references. All pretty basic stuff. > > Now I need to track all modifications to all fields, including the > relationship list objects. > > What is the best way to accomplish this task with SQLAlchemy? > > Is there some boilerplate available to support this, or do I have to carry > around two objects and compare them item by item? you can intercept changes on attributes using the attribute event system: http://docs.sqlalchemy.org/en/rel_0_8/orm/events.html#attribute-events otherwise you can get at the changes on an attribute after the fact (but before a flush) using the history interface: http://docs.sqlalchemy.org/en/rel_0_8/orm/session.html?highlight=history#sqlalchemy.orm.attributes.History you can get a list of all attributes mapped using mapper.attrs: http://docs.sqlalchemy.org/en/rel_0_8/orm/mapper_config.html?highlight=mapper.attrs#sqlalchemy.orm.mapper.Mapper.attrs signature.asc Description: Message signed with OpenPGP using GPGMail
[sqlalchemy] Modification tracking
Hi, being new to SQLAlchemy, I try to get my way through it. In an application, I have rather elaborate needs to track changes. I've defined 3 classes with declarative, where the main class has relationships with two auxiliary classes, that refer to the main class with foreign references. All pretty basic stuff. Now I need to track all modifications to all fields, including the relationship list objects. What is the best way to accomplish this task with SQLAlchemy? Is there some boilerplate available to support this, or do I have to carry around two objects and compare them item by item? TIA, Pete -- 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 http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/groups/opt_out.