首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用动态表生成完全刷新SQLAlchemy

用动态表生成完全刷新SQLAlchemy
EN

Stack Overflow用户
提问于 2014-08-04 12:46:26
回答 1查看 6K关注 0票数 6

我需要在一个for-循环中的不同位置创建许多类似的数据库。在循环的开头,我在磁盘上创建了一个新的path_sql_db引擎。

代码语言:javascript
运行
复制
    engine = sa.create_engine("sqlite:///{}".format(path_sql_db), echo=0, listeners=[util_sa.ForeignKeysListener()])
    Session = sa.orm.sessionmaker(bind=engine)
    session = Session()

然后,我在几个模块中的表继承了在外部模块中定义的DB_Base;

代码语言:javascript
运行
复制
from sqlalchemy.ext.declarative import declarative_base
DB_Base = declarative_base()

问题是,在for-循环的下一次迭代中,我无法创建我的表,因为它们仍然存在于某个地方?

代码语言:javascript
运行
复制
InvalidRequestError: Table 'vector_var01' is already defined for this MetaData instance.  
Specify 'extend_existing=True' to redefine options and columns on an existing Table object.

我试过从发动机上提取MetaData.drop_all();

代码语言:javascript
运行
复制
meta = sa.MetaData(bind = engine)
meta.reflect()
meta.drop_all()
session.close()

也来自基地;

代码语言:javascript
运行
复制
DB_Base.metadata.bind = engine
DB_Base.metadata.reflect()
DB_Base.metadata.drop_all()

没有成功,我仍然在黑暗中徘徊。

错误引用的是哪个MetaData实例?如何完全重置数据库代码的状态?

编辑

好的,我找到问题了。我试图动态地生成ORM表。我正在学习优化例程,并将设计空间变量存储在自己的表中,每个变量的可能值为一行。

最小的例子造成错误;

代码语言:javascript
运行
复制
from sqlalchemy import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
Base = declarative_base()

class Foo(Base):
    __tablename__ = 'foo'
    id = Column(Integer, primary_key=True)
    name = Column(String(50))

def generate_variable_table_class(name):
    """This is a helper function which dynamically creates a new ORM enabled class
    The table will hold the individual values of each variable
    Individual values are stored as a string
    """

    class NewTable( Base ):
        __tablename__ = "vector_{}".format(name)
        id = Column(Integer, primary_key=True)
        value = Column(String(16), nullable=False, unique=True)
        def __init__(self,value):
            self.value = str(value)

        def __str__(self):
            return self.value

        def __repr__(self):
            return self.value    


    NewTable.__name__ = "vector_ORM_{}".format(name)

    return NewTable


if __name__ == "__main__":

    for name in 'asfd', 'jkl', 'xyz':
        print("For loop: ",name)
        engine = create_engine(r'sqlite:///c:\testdelete\{}.sql'.format(name))
        Base.metadata.create_all(engine)
        Session = sessionmaker(bind=engine)
        session = Session()

        bunch_o_foos = [Foo(name = i) for i in range(10)]
        session.add_all(bunch_o_foos)
        session.commit()
        for foo in bunch_o_foos:
            print(foo.id)


        variables = [generate_variable_table_class(i) for i in range(10)]

它实际上与这个问题相同;Dynamic Python Class Definition in SQLAlchemy。这不可能吗?

EN

Stack Overflow用户

发布于 2014-08-04 16:49:05

最起码的例子是:

代码语言:javascript
运行
复制
from sqlalchemy import *
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

class Foo(Base):
    __tablename__ = 'foo'
    id = Column(Integer, primary_key=True)
    name = Column(String(50))

for name in 'asfd', 'jkl', 'xyz':
    engine = create_engine('sqlite:///{}'.format(name))
    Base.metadata.create_all(engine)

跑得很好。drop_all的意思是删除表,可能不是您想要的。一旦使用了bind,就会将元数据对象绑定到特定的引擎。尽管:

代码语言:javascript
运行
复制
Base.metadata.bind = engine
Base.metadata.create_all()

也适用于最小的例子。

编辑

根据示例案例,您将得到错误,因为您试图使用相同的vector_0子类定义一个具有相同表名的类,该类具有一个MetaData对象,该对象只能具有每个表名中的一个。

  • 在新的简单情况下,每个数据库的表之间没有区别,因此您应该将对generate_variable_table_class的调用从主循环中移出,并且只进行一次。
  • 如果您有每个数据库的行为,那么每次都可以使用一个新的Base (也就是将Foo移动到一个函数中!)(而且,对generate_variable_table_class的调用应该高于create_all,而不是在结束时)
  • 即使如此,sqlalchemy也不喜欢它们都被命名为NewTable。声明式ORM评估类定义,因此在设置NewTable之后,它会看到__name__。解决方案是不使用声明式系统(请参阅文档中的“经典映射”)。
  • 但另一种方法是扩展声明式元类以处理名称更改。declarative_base函数有一个显式的metaclass参数,因此这似乎在框架的规范中。要使用下面的方法,您需要在__name__ = "vector_ORM_{}".format(name)定义中设置NewTable。如果您希望非常干净,也可以更新__qualname__,尽管sqlalchemy在任何地方都不使用它。

代码语言:javascript
运行
复制
from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta

class NamingDeclarativeMeta(DeclarativeMeta):
    def __init__(cls, classname, bases, dict_):
        if '__name__' in cls.__dict__:
            cls.__name__ = classname = cls.__dict__['__name__']
        DeclarativeMeta.__init__(cls, classname, bases, dict_)

Base = declarative_base(metaclass=NamingDeclarativeMeta)
票数 4
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25119038

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档