2009-10-26 71 views
5

我想自动建立一个SA-映射 对象..的浅表副本此刻我的功能就是:的SQLAlchemy:浅拷贝避免延迟加载

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

,但我有麻烦懒惰的关系......显然GETATTR 触发延迟加载,但因为我并不需要它们的值正确 了,我想刚才复制的 属性的“这应该是延迟加载”状态.. 。 这可能吗?

编辑:我需要这个“数据记录”系统..也就是说,只要有人更新持久实体,我不得不产生一个新的记录,然后标记旧的这样。
为了做到这一点,我创建实体的浅表副本(所以SQLA发出INSERT而不是UPDATE)和工作从那里.. 该系统的工作原理相当不错(它已经在生产中使用了几个月),但现在我我想加强它,这样它就不需要所有的关系首先加载懒惰。

+0

是改变它的日志记录?它看起来更像是保持所有历史状态历史的版本控制系统。 – 2009-10-26 09:37:35

+0

没错,它保持,而不是'class_mapper(SRC .__类__)'实体 – Joril 2009-10-26 09:59:19

+1

的每一个版本,执行'object_mapper(SRC)'。避免直接访问'__foo__'属性。 – nosklo 2009-10-26 10:10:41

回答

6

您需要的仅仅是复制列属性,这可以使用isinstance(prop, sqlalchemy.orm.ColumnProperty)轻松过滤。请注意,您必须复制外部存储的关系(所有多对多),因为主表中没有与它们对应的列。这不能在没有延迟加载的高级界面下完成,所以我宁愿接受这种折衷。多对多关系可以通过isinstance(prop, RelationProperty) and prop.secondary测试来确定。生成的代码如下所示:

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)) 

还要注意,SQLAlchemy的设计是为了保持加载为每个标识单个对象,而你的副本打破了这种时候标识(主键)属性复制过,但是这如果您使用新的(版本化)标识符进行存储,则可能不是您的情况。

+0

好编辑的问题.. :) – Joril 2009-10-26 08:59:07