通过SQLAlchemy数据库反射创建模型

时间:2011-11-14 13:09:57

标签: python reflection sqlalchemy pyramid

我目前正在使用sqlalchemy的金字塔系统。

该系统将包含存储在a中的模型(我们称之为Base) 数据库表。用户可以在运行时扩展此模型。基本上,用户 应该能够继承Base并创建一个新模型(让我们称之为'Child')。 Childs应该存储在另一个数据库表中。

所有可用的示例似乎都处理预定义模型上的数据库反射。 通过数据库反射生成完整模型类的最佳方法是什么?

4 个答案:

答案 0 :(得分:4)

这似乎与“数据库反射”无关,而是与动态表创建有关。这是一个非常危险的操作,并且通常不赞成。

您应该尝试考虑如何为用户想要添加到Base的可能结构建模,并围绕它设计架构。有时,当您不知道列可能是什么时,这些灵活的结构可以从垂直表中获益良多。

不要忘记,有一整类数据存储系统可以为“无模式”模型提供更灵活的支持。像Mongo或ZODB这样的东西在这里可能更有意义。

答案 1 :(得分:2)

这个概念大部分都适用于我,但我无法将现有表绑定到新创建的类,该类使用多表继承。以下是一些使事情更清晰的代码:

Base.metadata.reflect(bind=Session.bind)
table = Base.metadata.tables['anExistingTable']
Extension = type('Extension', (BaseClass,), {})
orm.mapper(Extension, table, inherits=orm.class_mapper(BaseClass),
    polymorphic_identity='extension')

这会导致以下错误:

ArgumentError: Class '<class 'Extension'>' already has a primary mapper defined. Use non_primary=True to create a non primary Mapper. clear_mappers() will remove *all* current mappers from all classes.

您是否知道为什么在刚刚创建的类上定义了主映射器?

答案 2 :(得分:1)

只需定义一个生成器方法

def mapClass(class_name, table_name):
    # Allows to generate previously undefined mapped classes, remapping when necessary
    #For security reason this will only map a class 
    #when class is not previously declared
    #or if declared, when is a MappableClass subclass, 
    #this way we prevent to map any class.
    #Even when not able to return a mapped class it will return corresponding class_name class
    #if so, we'll get an error when accessing non existing MappableClass members
    if not globals.has_key(class_name):
        cls=type(class_name, (MappableClass,), {} )
        globals[class_name]=cls
    else:
        cls=globals[class_name]
    if issubclass(cls,MappableClass):
        tab_obj=Table(table_name,meta,autoload=True)
        mapper(cls, tab_obj)
    return cls

或将生成器类继承为here 我在响应的类中将生成器方法添加为静态,因此我可以使用先前声明的子类或新的dinamically创建的子类。

答案 3 :(得分:1)

我刚刚使用以下代码片段解决了上述问题:

table = Table('anExistingTable', Base.metadata, autoload=True, autoload_with=Session.bind)
Extension = type('Extension', (BaseClass,), {
    '__table__' : table,
    '__mapper_args__' : {
        'inherits': BaseClass,
        'polymorphic_identity': 'extension'
    }
})

然而,我不知道为什么第一次尝试没有成功...