重新创建一些sqlalchemy对象
好的,我遇到了一点问题。我需要为一些 sqlalchemy 创建一种导入/导出功能。不过这些不是我自己定义的对象,所以我获取列的方式是:
for attr, value in res.__class__.__dict__.iteritems():
if isinstance(value, InstrumentedAttribute):
data = eval("res." + str(attr))
param_dict[attr] = data
这样可以正确获取到那个对象的属性。但是,我不能确定 init 方法的参数是否是一样的,因为我并不是在处理这些对象的人。所以可能会出现这样的情况:
class SomeClass(model.Base):
my_column = Column(String)
....some other stuff...
def __init__(self, mycolumn, ...):
self.my_column = mycolumn
在这种情况下,我没有字段名称和 init 方法接收到的参数名称之间的对应关系。目前我要求定义这些类的人给所有的 init 参数设置默认值,这样我就可以:
obj = SomeClass()
exec "obj." + attr + " = " + param[attr]
不过我希望能摆脱这个限制。有没有什么办法可以做到这一点呢?
1 个回答
4
序列化并不能简单地适用于所有可能的sqlalchemy映射类,因为这些类可能有一些属性并没有存储在数据库中,或者需要通过多个层级的关系属性来推断。简单来说,只有你知道如何为特定的用途序列化某个特定的类。
假设你只关心特定类的特定实例(在res
中)的列值。这里有一个简单的函数,可以返回一个只包含这些值的字典。
from sqlalchemy.orm.attributes import manager_of_class
from sqlalchemy.orm.properties import ColumnProperty
def get_state_dict(instance):
cls = type(instance)
mgr = manager_of_class(cls)
return dict((key, getattr(instance, key))
for key, attr in mgr.iteritems()
if isinstance(attr.property, ColumnProperty))
然后可以通过这个字典重新创建一个实例*
def create_from_state_dict(cls, state_dict):
mgr = manager_of_class(cls)
instance = mgr.new_instance()
for key, value in state_dict.iteritems():
setattr(instance, key, value)
return instance
如果你需要更复杂的东西,比如处理那些没有显示为列的关系(比如多对多关系),你可以通过查找sqlalchemy.orm.properties.RelationshipProperty
来处理这种情况,然后遍历这个集合。
*序列化中间的字典和类留给你自己去练习。