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

发布于 2024-12-15 20:55:45 字数 223 浏览 1 评论 0原文

我目前正在开发一个使用 sqlalchemy 的金字塔系统。

该系统将包括一个模型(我们称之为 Base),该模型存储在 数据库表。该模型应该可以由用户在运行时扩展。基本上,用户 应该能够对 Base 进行子类化并创建一个新模型(我们称其为“Child”)。 Childs 应存储在另一个数据库表中。

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

I am currently working on a pyramid system that uses sqlalchemy.

This system will include a model (let's call it Base) that is stored in a
database table. 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').
Childs should be stored in another database table.

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

我恋#小黄人 2024-12-22 20:55:45

这似乎与“数据库反射”没有太大关系,而是与动态表创建有关。这是一个相当危险的操作,通常会令人不悦。

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

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

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

二货你真萌 2024-12-22 20:55:45

这个概念的大部分内容对我来说都很好,但我无法将现有表绑定到新创建的类,该类使用多表继承。这里有一些代码可以让事情变得更清楚:

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.

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

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?

比忠 2024-12-22 20:55:45

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

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

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

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

深海夜未眠 2024-12-22 20:55:45

只需定义一个生成器方法

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

或继承一个生成器类 此处
我在答案的类中将生成器方法添加为静态,因此我可以使用先前声明的子类或新的动态创建的子类。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文