flask_sqlalchemy的session用法疑问

libraco
  • 760

flask_sqlalchemy的官方文档用法如下:

>>> from yourapplication import User
>>> admin = User(username='admin', email='admin@example.com')
>>> guest = User(username='guest', email='guest@example.com')
>>> db.session.add(admin)
>>> db.session.add(guest)
>>> db.session.commit()

这里db.session可以直接使用,它是一个sqlalchemy.orm.scoping.scoped_session对象,但是我们看过sqlalchemy的教程就知道,sqlalchemy里推荐的用法需要把session实例化使用:

import sqlalchemy
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
engine = create_engine(uri, convert_unicode=True)
session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine))
sess = session()
sess.add(admin)
sess.commit()
sess.close()

此时的sess是一个sqlalchemy.orm.session.SignallingSession对象,用法和之前差不多,但是具体的区别是什么呢?

回复
阅读 5.4k
3 个回答
✓ 已被采纳

其实flask_sqlalchemy中使用session之前也是做了session实例化的,只不过这个动作通过proxy的编程技巧被隐藏在scoped_session类中了。《sqlalchemy 1.4 Documentation》中会话章节有提及这种隐式方法访问

Session = scoped_session(some_factory)

# equivalent to:
#
# session = Session()
# print(session.query(MyClass).all())
#
print(Session.query(MyClass).all())

flask_sqlalchemy帮助使用者简化了session实例化的过程,具体的做法是通过scoped_session._call_ 这个魔术函数来自动完成session实例化的,这里是代码实现片段

class scoped_session(object):
    def __call__(self, **kw):
        r"""Return the current :class:`.Session`, creating it
        using the :attr:`.scoped_session.session_factory` if not present.
        :param **kw: Keyword arguments will be passed to the
            :attr:`.scoped_session.session_factory` callable, if an existing
            :class:`.Session` is not present.  If the :class:`.Session` is present
            and keyword arguments have been passed,
            :exc:`~sqlalchemy.exc.InvalidRequestError` is raised.
        """
        if kw:
            if self.registry.has():
                raise sa_exc.InvalidRequestError(
                    "Scoped session is already present; "
                    "no new arguments may be specified."
                )
            else:
                sess = self.session_factory(**kw)
                self.registry.set(sess)
                return sess
        else:
            return self.registry()

scoped_session好像是一个轮巡,这样写的化好像是支持并发

lift
  • 5
新手上路,请多包涵
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏