简体   繁体   English

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

[英]Model Creation by SQLAlchemy database reflection

I am currently working on a pyramid system that uses sqlalchemy. 我目前正在使用sqlalchemy的金字塔系统。

This system will include a model (let's call it Base) that is stored in a database table. 该系统将包括存储在数据库表中的模型(我们称之为Base)。 This model should be extensible by the user on runtime. 用户可以在运行时扩展此模型。 Basically, the user should be able to subclass the Base and create a new model (let's call this one 'Child'). 基本上,用户应该能够继承Base并创建一个新模型(让我们称之为'Child')。 Childs should be stored in another database table. Childs应存储在另一个数据库表中。

All examples available seem to handle database reflection on a predefined model. 所有可用的示例似乎都处理预定义模型上的数据库反射。 What would be the best way to generate complete model classes via database reflection? 通过数据库反射生成完整模型类的最佳方法是什么?

This doesn't seem to have much to do with "database reflection", but rather dynamic table creation. 这似乎与“数据库反射”无关,而是与动态表创建有关。 This is a pretty dangerous operation and generally frowned upon. 这是一个非常危险的操作,并且通常不赞成。

You should try to think about how to model the possible structure your users would want to add to the Base and design your schema around that. 您应该尝试考虑如何为用户想要添加到Base的可能结构建模,并围绕它设计架构。 Sometimes these flexible structures can benefit a lot from vertical tables when you don't know what the columns may be. 有时,当您不知道列可能是什么时,这些灵活的结构可以从垂直表中受益匪浅。

Don't forget that there's an entire class of data storage systems out there that provide more flexible support for "schemaless" models. 不要忘记,有一整类数据存储系统可以为“无模式”模型提供更灵活的支持。 Something like Mongo or ZODB might make more sense here. 像Mongo或ZODB这样的东西在这里可能更有意义。

Most of this concept works fine for me, but I fail to bind an existing table to a newly created class, which uses multi-table inheritance. 大多数这个概念对我来说都很好,但是我无法将现有表绑定到新创建的类,该类使用多表继承。 Here is some code to make things more clear: 以下是一些使事情更清晰的代码:

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

This results in the following error: 这会导致以下错误:

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.

Do you have any idea why there is a primary mapper defined on a class that has just been created? 您是否知道为什么在刚刚创建的类上定义了主映射器?

Just define a generator method 只需定义一个生成器方法

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

or inherit a generator class as here I added the generator method as static in the answer's class, so I can use both previously declared child classes or new dinamically-created, ones. 或继承发电机类作为这里我增加了发电机方法在答题的类为静态的,所以我可以同时使用以前声明的子类或新dinamically创建的,那些。

I just solved the problem described above by using the following code snippet: 我刚刚使用以下代码片段解决了上述问题:

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

However, I don't know why the first try didn't work out... 但是,我不知道为什么第一次尝试没有成功...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM