use*_*855 3 python sqlalchemy flask
我接手了一个flask应用程序,但它没有使用flask-sqlalchemy插件。我很难理解它是如何设置的。
它有一个database.py文件。
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, scoped_session, Session
_session_factory = None
_scoped_session_cls = None
_db_session: Session = None
def _get_session_factory():
global _session_factory
if _session_factory is None:
_session_factory = sessionmaker(
bind=create_engine(CONNECTION_URL)
)
return _session_factory
def new_session():
session_factory = _get_session_factory()
return session_factory()
def new_scoped_session():
global _scoped_session_cls
if _scoped_session_cls is None:
session_factory = _get_session_factory()
if not session_factory:
return
_scoped_session_cls = scoped_session(session_factory)
return _scoped_session_cls()
def init_session():
global _db_session
if _db_session is not None:
log.warning("already init")
else:
_db_session = new_scoped_session()
return _db_session
def get_session():
return _db_session
Run Code Online (Sandbox Code Playgroud)
我们启动 Flask 应用程序,它会调用database.init_session(),然后每当我们想要使用它调用的数据库时database.get_session()。
这是与数据库交互的正确/安全方式吗?如果两个请求同时由不同的线程处理,会发生什么情况?这是否会导致两者使用同一会话的交叉污染
为了解释代码中发生的情况,让我们首先深入了解如何sqlalchemy连接到数据库:
create_engine()function创建的。
engine.connect()使用->
连接到您的数据库,这将打开一个到您的数据库的连接。此时,您可以直接连接数据库:
engine = create_engine(...)
with engine.connect() as connection:
result = connection.execute(...)
Run Code Online (Sandbox Code Playgroud)
请注意,在事务完成/连接关闭之前,不能保证在此连接上下文中创建/更改的对象共享连接上下文之外的状态。
要执行更复杂的查询(例如:选择和插入的混合),您将需要使用会话。
engine对象创建的:
with Session(engine) as session:
...
Run Code Online (Sandbox Code Playgroud)
sessionmaker()工厂方法创建:
with Session(engine) as session:
...
Run Code Online (Sandbox Code Playgroud)
上面代码的目的过于简单化,是通过get_session().
最初,这将返回None,因为这是 的值_db_session。
因此,您必须调用init_session()它将创建返回会话所需的各种对象get_session()。
以下是其中发生的事情init_session():
new_scoped_session()将返回session_factory_get_session_factory()将创建的调用- session_factory> 请注意它如何engine从CONNECTION_URLscoped_session(session_factory)创建范围会话并分配给 的调用_scoped_session_cls。
注意:这与常规会话非常相似,只是更加隔离(并且安全)。许多复杂性与状态缓存有关。本质上,该代码正在执行以下操作:
Session = sessionmaker(engine)
Run Code Online (Sandbox Code Playgroud)
我希望这可以帮到你。祝你好运!