我想使用自动加载来使用现有数据库。我知道如何在没有声明性语法的情况下做到这一点(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=
将元数据与引擎关联将引擎传递给表,或通过metadata.bind=
这里的问题是,在导入模型的阶段(在 init_model() 中可用),我不知道从哪里获取引擎(在 autoload_with 中使用它)。我尝试添加
meta.Base.metadata.bind(engine)
到environment.py,但它不起作用。有人找到了一些优雅的解决方案吗?
好吧,我想我明白了。解决方案是在
model/__init__.py
之外声明模型对象。我得出的结论是,当从模块导入某些内容时(在本例中为 __init__.py
),model
会作为第一个文件导入,这会导致问题,因为模型对象是在调用 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
我刚刚使用 orm 模块尝试过这个。
Base = declarative_base(bind=engine)
Base.metadata.reflect(bind=engine)
手动或通过循环或其他方式访问表:
Base.metadata.sorted_tables
可能有用。
查看将 SQLAlchemy 与 Pylons 一起使用教程,了解如何在
init_model
函数中将元数据绑定到引擎。
如果
meta.Base.metadata.bind(engine)
语句成功将模型元数据绑定到引擎,您应该能够在自己的 init_model
函数中执行此初始化。我猜你并不是想跳过这个函数中的元数据绑定,是吗?
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()
对象时未指定绑定。
为旧问题提供更新的答案。
尽管原始答案中的方法效果很好,但
sqlalchemy
文档中推荐的方法是不同的
根据文档。
reflect()
对象上调用 metadata
方法__table__
属性这是代码
import sqlalchemy as sql
engine = sql.orm.create_engine("postgresql+psycopg2://user:pass@hostname/my_existing_database")
class Base(sql.orm.DeclarativeBase):
pass
Base.metadata.reflect(engine)
class MyClass(Base):
__table__ = Base.metadata.tables["mytable"]
参考资料:
https://docs.sqlalchemy.org/en/20/orm/declarative_tables.html#orm-declarative-reflected