SQLAlchemy 中的动态类创建

Posted

技术标签:

【中文标题】SQLAlchemy 中的动态类创建【英文标题】:Dynamic Class Creation in SQLAlchemy 【发布时间】:2011-02-15 15:38:24 【问题描述】:

我们需要创建 SQLAlchemy 类来访问多个外部数据源,这些数据源的数量会随着时间的推移而增加。我们为核心 ORM 模型使用声明式基础,我知道我们可以使用 autoload=True 手动指定新的 ORM 类来自动生成映射。

问题是我们需要能够动态生成它们,如下所示:

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

stored=
stored['tablename']='my_internal_table_name'
stored['objectname']='MyObject'

并动态地把它变成这样的东西:

class MyObject(Base):
    __tablename__ = 'my_internal_table_name'
    __table_args__ = 'autoload':True

我们不希望类的持续时间超过打开连接、执行查询然后关闭连接所需的时间。因此,理想情况下,我们可以将上面“存储”变量中的项目放入数据库中,并根据需要拉取它们。另一个挑战是对象名称(例如“MyObject”)可能用于不同的连接,因此我们无法定义一次并保留它。

任何关于如何实现这一点的建议将不胜感激。

谢谢...

【问题讨论】:

【参考方案1】:

您可以使用3-argument call to type动态创建MyObject

type(name, bases, dict)

    Return a new type object. This is essentially a dynamic form of the 
    class statement... 

例如:

mydict='__tablename__':stored['tablename'],
        '__table_args__':'autoload':True,

MyObj=type(stored['objectname'],(Base,),mydict)
print(MyObj)
# <class '__main__.MyObject'>
print(MyObj.__base__)
# <class '__main__.Base'>
print(MyObj.__tablename__)
# my_internal_table_name
print(MyObj.__table_args__)
# 'autoload': True

【讨论】:

男孩……我觉得自己很笨。这么简单的解决方案。我没有意识到 type 方法如此强大。我稍微修改了解决方案,将对象名称放在全局空间中,以便它可以直接包含在 SQLAlchemy 查询中: globals()[stored['objectname']]=type(stored['objectname'],(Base,), mydict)谢谢...很好的解决方案。 别觉得自己笨!我通过观看其他人在 SO 上使用它来学习这个技巧。现在您也知道诀窍了,可以让您的朋友惊叹不已。 :) @unutbu 你需要额外的分隔逗号以便调用 type 意识到它们只是第一个参数吗? 这个线程有点老了,但是我在任何地方都找不到解决方案,如何在 api 调用期间在其他地方重用 MyObj?因为如果我调用工厂两次,就会抛出一个表名已经存在的错误

以上是关于SQLAlchemy 中的动态类创建的主要内容,如果未能解决你的问题,请参考以下文章

SQLAlchemy模型中的进程字段(使用flask_sqlalchemy)

python SQLAlchemy

Sqlalchemy 动态创建表和映射类

sqlalchemy根据表名动态创建model类

使用 sqlalchemy 实现“软删除”系统

SQLAlchemy-ORM