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

13 投票
4 回答
11222 浏览
提问于 2025-04-16 08:59

我想用自动加载功能来使用一个已经存在的数据库。我知道怎么在不使用声明式语法的情况下做到这一点(在 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: 这个表的元数据没有绑定到任何引擎。请通过 autoload_with=<someengine> 将引擎传递给这个表,或者通过 metadata.bind=<someengine> 将元数据与引擎关联。

这里的问题是,我不知道从哪里获取引擎(以便在 autoload_with 中使用),因为在导入模型的时候它是不可用的(它在 init_model() 中可用)。我尝试在 environment.py 中添加

meta.Base.metadata.bind(engine)

但这并没有奏效。有没有人找到什么优雅的解决方案?

4 个回答

1
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() 对象时没有指定绑定。

1

我刚刚尝试了一下使用orm模块。

Base = declarative_base(bind=engine)

Base.metadata.reflect(bind=engine)

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

Base.metadata.sorted_tables

这可能会很有用。

12

好的,我想我搞明白了。解决办法是把模型对象的声明放在 model/__init__.py 文件之外。我发现当从一个模块(在这个例子中是 model)导入东西时,__init__.py 会被首先导入,这就会造成问题,因为模型对象在调用 init_model() 之前就被声明了。

为了避免这个问题,我在 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

撰写回答