前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SQL炼金术

SQL炼金术

作者头像
用户7466307
发布2020-06-17 16:08:22
6110
发布2020-06-17 16:08:22
举报
文章被收录于专栏:用户7466307的专栏

使用非全局会话

有时最好不要使用SQLAlchemy的线程作用域会话(例如,当您需要在异步系统中使用Pyramid时)。幸运的是,这样做很容易。您可以将会话工厂存储在应用程序的注册表中,并调用会话工厂作为向请求对象询问属性的副作用。然后,会话对象的生存期将与请求的生存期匹配。

我们将使用Configurator.add_request_method添加SQLAlchemy会话来请求对象并Request.add_finished_callback关闭该会话。

我们假设您有一个.ini文件,其sqlalchemy.设置可以正确指定数据库:

现在,SQLAlchemy会话在视图代码中以request.db或 可用config.registry.dbmaker()。

代码语言:javascript
复制
# __init__.py

from pyramid.config import Configurator
from sqlalchemy import engine_from_config
from sqlalchemy.orm import sessionmaker

def db(request):
    maker = request.registry.dbmaker
    session = maker()

def cleanup(request):
        if request.exception is not None:
            session.rollback()
        else:
            session.commit()
        session.close()
    request.add_finished_callback(cleanup)

    return session

def main(global_config, **settings):
    config = Configurator(settings=settings)
    engine = engine_from_config(settings, prefix='sqlalchemy.')
    config.registry.dbmaker = sessionmaker(bind=engine)
    config.add_request_method(db, reify=True)

# .. rest of configuration ...

导入所有SQLAlchemy模型

如果您使用粘贴程序模板创建了Pyramid项目,则默认情况下,SQLAlchemy模型将驻留在单个文件中。这只是按照惯例。如果您希望有一个用于SQLAlchemy模型的目录而不是一个文件,那么您当然可以创建一个充满模型模块的Python包,将models.py文件替换models为Python包的目录(其中包含的目录__init__.py),例如每个 修改包的结构。但是,由于SQLAlchemy的“声明式”配置模式的行为,必须先导入所有保存活动SQLAlchemy模型的模块,然后才能成功使用它们。因此,如果您使用具有声明性基础的模型类,则需要找出一种方法来导入所有模型模块,以便能够在应用程序中使用它们。

您可能首先创建一个models目录,替换该models.py 文件,然后在其中创建一个名为的文件models/__init__.py。此时,您可以添加名为的子模块models/mymodel.py,其中包含一个 MyModel模型类。在models/__init__.py将定义声明性基类和全局DBSession对象,其中每个子模块模型(如models/mymodel.py)将需要导入。然后,您所需要做的就是在中添加每个子模块的导入models/__init__.py。

但是,当您将models包子模块import语句添加到时 models/__init__.py,这将导致循环导入依赖关系。该 models/__init__.py模块的进口mymodel和models/mymodel.py 进口models包。下次尝试启动您的应用程序时,由于这种循环依赖性,它会因导入错误而失败。

Pylons 1通过创建一个models/meta.py模块来解决此问题,在该模块中创建DBSession和声明性基础对象。该 models/__init__.py文件的每个子模块models的进口 DBSession和declarative_base从它。每当您.py 在models包中创建文件时,都希望为其添加导入 models/__init__.py。主程序将导入models包,这具有确保已导入所有模型类的副作用。您也可以执行此操作,效果很好。

但是,您可以交替使用config.scan()它的副作用。使用config.scan()可以避免之间的麻烦, models/__init__.py而models/themodel.py无需创建特殊的 models/meta.py。

例如,如果您在中执行此操作myapp/models/__init__.py:

代码语言:javascript
复制
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session, sessionmaker

DBSession = scoped_session(sessionmaker())
Base = declarative_base()

def initialize_sql(engine):
    DBSession.configure(bind=engine)
    Base.metadata.bind = engine
    Base.metadata.create_all(engine)

而在myapp/models/mymodel.py

代码语言:javascript
复制
from myapp.models import Base
from sqlalchemy import Column
from sqlalchemy import Unicode
from sqlalchemy import Integer

class MyModel(Base):
    __tablename__ = 'models'
    id = Column(Integer, primary_key=True)
    name = Column(Unicode(255), unique=True)
    value = Column(Integer)

def __init__(self, name, value):
        self.name = name
        self.value = value

而在myapp/__init__.py

代码语言:javascript
复制
from sqlalchemy import engine_from_config
from myapp.models import initialize_sql

def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
    """
    config = Configurator(settings=settings)
    config.scan('myapp.models') # the "important" line
    engine = engine_from_config(settings, 'sqlalchemy.')
    initialize_sql(engine)
# other statements here
    config.add_handler('main', '/{action}',
                     'myapp.handlers:MyHandler')
    return config.make_wsgi_app()

上面的重要行是config.scan('myapp.models')。config.scan 具有对给定的程序包名称进行递归导入的副作用。此副作用可确保myapp.models导入其中的每个文件,而无需您在其中“手工”导入每个 文件models/__init__.py。但是,它不会导入任何不在myapp.models包装内的模型 。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-03-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 软件测试test 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 导入所有SQLAlchemy模型
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档