【问题标题】:Dynamic Class Creation in SQLAlchemySQLAlchemy 中的动态类创建
【发布时间】: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”)可能用于不同的连接,因此我们无法定义一次并保留它。

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

谢谢...

【问题讨论】:

    标签: python sqlalchemy metaprogramming metaclass declarative


    【解决方案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?因为如果我调用工厂两次,就会抛出一个表名已经存在的错误
    猜你喜欢
    • 2020-06-22
    • 2018-12-18
    • 2017-07-04
    • 2020-05-10
    • 2014-10-03
    • 2017-09-29
    • 2010-11-01
    • 2017-10-04
    • 1970-01-01
    相关资源
    最近更新 更多