Pylons中具有自动加载(反射)功能的SQLAlchemy声明性语法

发布于 2021-01-29 17:12:48

我想使用自动加载功能来使用现有数据库。我知道如何不使用声明性语法(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:此表的MetaData没有绑定任何引擎。通过autoload_with =
将引擎传递到表,或通过metadata.bind = 将元数据与引擎关联

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

meta.Base.metadata.bind(engine)

到environment.py,但不起作用。任何人都找到了一些优雅的解决方案?

关注者
0
被浏览
44
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    好吧,我想我明白了。解决方案是在之外声明模型对象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
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看