gpt4 book ai didi

python - Flask 如何在每个请求开始时启动一个新的 SQLAlchemy 事务?

转载 作者:太空宇宙 更新时间:2023-11-04 05:39:36 24 4
gpt4 key购买 nike

我尝试使用 this method 完全分离 Flask 和 SQLAlchemy但是 Flask 似乎仍然能够检测到我的数据库并在每个请求开始时启动一个新事务。

db.py 文件创建一个新 session 并定义一个简单的表模型:

from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, String


engine = create_engine("mysql://web:kingtezdu@localhost/web_unique")

print("creating new session")
db_session = scoped_session(sessionmaker(bind=engine))

Base = declarative_base()
Base.query = db_session.query_property()


# define model of 'persons' table
class Person(Base):
__tablename__ = "persons"
name = Column(String(30), primary_key=True)

def __repr__(self):
return "Person(\"{0.name}\")".format(self)

# create table
Base.metadata.create_all(bind=engine)

还有 app.py,一个使用 SQLAlchemy session 和模型的简单 Flask 应用程序:

from flask import Flask, escape
app = Flask(__name__)


# importing new session
from db import db_session, Person

# registering for app teardown to remove session
@app.teardown_appcontext
def shutdown_session(exception=None):
db_session.remove()


@app.route("/query")
def query():
# query all persons in the database
all_persons = Person.query.all()
print all_persons
return "" # we use the console output


if __name__ == "__main__":
app.run(debug=True)

让我们运行这个:

$ python app.py 
creating new session
* Running on http://127.0.0.1:5000/
* Restarting with reloader
creating new session

奇怪的是它运行了两次 db.py 但我们忽略了这一点,让我们访问网页 /query:

[]
127.0.0.1 - - [23/Dec/2015 18:20:14] "GET /query HTTP/1.1" 200 -

虽然我们只使用控制台输出,但我们可以看到我们的请求已得到答复。数据库中还没有Person,让我们添加一个:

mysql> INSERT INTO persons (name) VALUES ("Marie");
Query OK, 1 row affected (0.11 sec)

Marie 现在是数据库的一部分,因此我们重新加载网页:

[Person("Marie")]
127.0.0.1 - - [23/Dec/2015 18:24:48] "GET /query HTTP/1.1" 200 -

如您所见, session 已经知道Marie。 Flask 没有创建新 session 。这意味着有一个新的交易开始了。将此与下面的计划 python 示例进行对比,以了解不同之处。

我的问题是 Flask 如何能够在每个请求开始时启动新事务。 Flask 不应该知道数据库,但似乎能够改变它的某些行为。


如果您不知道什么是 SQLAlchemy 事务,请阅读摘自 Managing Transactions 的这一段:

When the transactional state is completed after a rollback or commit, the Session releases all Transaction and Connection resources, and goes back to the “begin” state, which will again invoke new Connection and Transaction objects as new requests to emit SQL statements are received.

因此事务由提交结束,并会导致建立新的连接,然后使 session 再次读取数据库。实际上,这意味着当您想要查看对数据库所做的更改时必须提交:

首先在交互式python模式下:

>>> from db import db_session, Person
creating new session
>>> Person.query.all()
[]

切换到 MySQL 并插入一个新的 Person:

mysql> INSERT INTO persons (name) VALUES ("Paul");
Query OK, 1 row affected (0.03 sec)

最后尝试将 Paul 加载到我们的 session 中:

>>> Person.query.all()
[]
>>> db_session.commit()
>>> Person.query.all()
[Person("Paul")]

最佳答案

我认为这里的问题是 scoped_session 在某种程度上隐藏了实际使用中的 session 发生了什么。当你的拆卸处理程序

# registering for app teardown to remove session
@app.teardown_appcontext
def shutdown_session(exception=None):
db_session.remove()

在每个请求结束时运行,您调用 db_session.remove() 处理该特定请求中使用的 session 以及任何事务上下文。参见 http://docs.sqlalchemy.org/en/latest/orm/contextual.html详细信息,特别是

The scoped_session.remove() method first calls Session.close() on the current Session, which has the effect of releasing any connection/transactional resources owned by the Session first, then discarding the Session itself. “Releasing” here means that connections are returned to their connection pool and any transactional state is rolled back, ultimately using the rollback() method of the underlying DBAPI connection.

关于python - Flask 如何在每个请求开始时启动一个新的 SQLAlchemy 事务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34440860/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com