在Pylons中使用自动加载(反射)的SQLAlchemy声明性语法

时间:2010-12-24 13:02:39

标签: python reflection sqlalchemy pylons declarative

我想使用自动加载来使用现有数据库。我知道如何在没有声明性语法的情况下做到这一点(model / _ init _.py):

def init_model(engine):
    """Call me before using any of the tables or classes in the model"""
    t_events = Table('events', Base.metadata, schema='events', autoload=True, autoload_with=engine)
    orm.mapper(Event, t_events)

    Session.configure(bind=engine)  

class Event(object):
    pass

这很好用,但我想使用声明性语法:

class Event(Base):
    __tablename__ = 'events'
    __table_args__ = {'schema': 'events', 'autoload': True}

不幸的是,这样我得到了:

  

sqlalchemy.exc.UnboundExecutionError:没有引擎绑定到此Table的MetaData。通过autoload_with =< someengine>将引擎传递给表,或通过metadata.bind =< someengine>

将MetaData与引擎相关联

这里的问题是我不知道在导入模型的阶段从哪里获取引擎(在autoload_with中使用它)(它在init_model()中可用)。我尝试添加

meta.Base.metadata.bind(engine)

到environment.py但它不起作用。有人找到了一些优雅的解决方案吗?

4 个答案:

答案 0 :(得分:11)

好吧,我想我弄明白了。解决方案是在model/__init__.py之外声明模型对象。我得出结论,当从模块导入某些内容时__init__.py作为第一个文件导入(在本例中为model),这会导致问题,因为在调用init_model()之前声明了模型对象。 / p>

为避免这种情况,我在model模块中创建了一个新文件,例如objects.py。然后我在此文件中声明了所有模型对象(如Event)。

然后,我可以像这样导入我的模型:

from PRJ.model.objects import Event

此外,为避免为每个表格指定autoload-with,我在init_model()末尾添加了这一行:

Base.metadata.bind = engine

这样我可以声明我的模型对象没有样板代码,如下所示:

class Event(Base):
    __tablename__ = 'events'
    __table_args__ = {'schema': 'events', 'autoload': True}

    event_identifiers = relationship(EventIdentifier)

    def __repr__(self):
        return "<Event(%s)>" % self.id

答案 1 :(得分:1)

我刚刚尝试使用orm模块。

Base = declarative_base(bind=engine)

Base.metadata.reflect(bind=engine)

手动或通过循环或其他方式访问表:

Base.metadata.sorted_tables

可能有用。

答案 2 :(得分:0)

init_model函数中查看有关如何将元数据绑定到引擎的Using SQLAlchemy with Pylons tutorial

如果meta.Base.metadata.bind(engine)语句成功将模型元数据绑定到引擎,您应该能够在自己的init_model函数中执行此初始化。我想你不是故意在这个函数中跳过元数据绑定,是吗?

答案 3 :(得分:0)

from sqlalchemy import MetaData,create_engine,Table
engine = create_engine('postgresql://postgres:********@localhost/db_name')

metadata = MetaData(bind=engine)

rivers = Table('rivers',metadata,autoload=True,auto_load_with=engine)

from sqlalchemy import select

s = select([rivers]).limit(5)
engine.execute(s).fetchall()

为我工作。我收到错误消息是因为在创建MetaData()对象时未指定绑定。