重新创建一些sqlalchemy对象

时间:2011-08-30 07:22:16

标签: python 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 个答案:

答案 0 :(得分:4)

序列化不能真正推广到所有可能的sqlalchemy映射类,类可能具有未存储在数据库中的属性,或者必须通过relationship属性跨多个间接层推断。简而言之,只有你知道如何为特定用途序列化特定类。


让我们假装您只需要或关心所考虑的特定类的特定实例的列值(在res中)。这是一个粗略函数,它将返回仅包含这些值的dict。

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

并从dict *

重新创建一个实例
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来添加该案例,然后迭代集合

* 序列化中间词典和类作为练习。