SQLAlchemy中的动态类创建

28
我们需要创建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个回答

35

您可以使用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)谢谢...好棒的解决方案。 - PlaidFan
4
不要觉得自己蠢!我是在Stack Overflow上看别人用这个技巧,学会了它。现在你也知道了这个技巧,可以给你的朋友留下深刻印象。 :) - unutbu
@unutbu,您需要额外的逗号分隔符,以便调用类型意识到它们只是第一个参数吗? - MattSom
这个线程有点老了,但是我找不到解决方案,我该如何在 API 调用期间重复使用 MyObj? 因为如果我调用工厂两次,就会抛出一个表名已经存在的错误。 - Kais Ben Daamech

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接