通过SQLAlchemy数据库反射创建模型
我现在正在开发一个使用sqlalchemy的金字塔系统。
这个系统会有一个模型(我们称它为Base),它会存储在数据库表中。这个模型应该允许用户在运行时进行扩展。简单来说,用户应该能够从Base派生出一个新的模型(我们称这个为'Child')。Child模型会存储在另一个数据库表中。
目前所有的例子似乎都是在处理一个预定义模型的数据库反射。通过数据库反射生成完整的模型类,最好的方法是什么呢?
4 个回答
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.
你知道为什么在一个刚创建的类上会定义一个主映射器吗?
4
这看起来和“数据库反射”没什么关系,更像是动态创建表格。这种操作其实挺危险的,通常不太被推荐。
你应该考虑一下用户可能想要添加的结构,然后围绕这个设计你的数据库结构。有时候,当你不知道具体会有哪些列时,使用垂直表格会对这些灵活的结构有很大帮助。
别忘了,还有一类数据存储系统可以提供更灵活的“无模式”支持。像Mongo或者ZODB这样的工具在这里可能更合适。
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'
}
})
不过,我不知道为什么第一次尝试没有成功……