开发者

SQLAlchemy: Shallow copy avoiding lazy loading

开发者 https://www.devze.com 2022-12-09 16:13 出处:网络
I\'m trying to automatically build a shallow copy of a SA-mapped object.. At th开发者_开发技巧e moment my function is just:

I'm trying to automatically build a shallow copy of a SA-mapped object.. At th开发者_开发技巧e moment my function is just:

newobj = src.__class__()
for prop in class_mapper(src.__class__).iterate_properties:
    setattr(newobj, prop.key, getattr(src, prop.key))

but I'm having troubles with lazy relations... Obviously getattr triggers the lazy loading, but since I don't need their values right away, I'd like to just copy the "this should be lazy loaded"-state of the attribute... Is this possible?

Edit: I need this for a "data logging" system.. That is, whenever someone updates a persisted entity, I have to generate a new record and then mark the old one as such.

In order to do this I create a shallow copy of the entity (so SQLA issues an INSERT instead of an UPDATE) and work from there.. The system works quite nicely (it's been in production use for months) but now I'd like to enhance it so that it won't need that all the relations get lazy-loaded first..


What you need is to copy column properties only, which can be easily filtered using isinstance(prop, sqlalchemy.orm.ColumnProperty). Note, that you HAVE to copy externally stored relations (all many-to-many), since there is no columns corresponding to them in the main table. This can't be done with high-level interface without lazy-loading, so I'd prefer to accept this trade-off. Many-to-many relations can be determined with isinstance(prop, RelationProperty) and prop.secondary test. The resulting code will look like the following:

from sqlalchemy.orm import object_mapper, ColumnProperty, RelationProperty

newobj = type(src)()
for prop in object_mapper(src).iterate_properties:
    if (isinstance(prop, ColumnProperty) or
        isinstance(prop, RelationProperty) and prop.secondary):
    setattr(newobj, prop.key, getattr(src, prop.key))

Also note, that SQLAlchemy is designed to maintain single object loaded for each identity, while your copy breaks this when identity (primary key) properties are copied too, but this is probably not your case if your are storing with new (versioned) identifier.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号