mun*_*nch 5 python flask flask-sqlalchemy
我正在使用Flask-Testing,它说:
另一个问题是Flask-SQLAlchemy还会在每个请求结束时删除会话实例(正如使用带有scoped_session的SQLAlchemy的任何线程安全应用程序一样).因此,每次调用client.get()或其他客户端方法时,会话都会与添加到其中的任何对象一起清除.
但是,我没有看到.此测试失败:
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.testing import TestCase
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = SQLAlchemy(app)
@app.route('/')
def index():
print 'before request:', `db.session`
u = db.session.query(User).first()
u.name = 'bob'
return ''
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String)
class SessionTest(TestCase):
def create_app(self):
return app
def test_remove(self):
db.drop_all()
db.create_all()
u = User()
u.name = 'joe'
db.session.add(u)
db.session.commit()
client = app.test_client()
client.get('/')
print 'after request:', `db.session`
print u.name
assert u not in db.session
Run Code Online (Sandbox Code Playgroud)
(运行$ nosetests test_file.py以查看它的运行情况.)
标准输出:
-------------------- >> begin captured stdout << ---------------------
before request: <sqlalchemy.orm.scoping.ScopedSession object at 0x10224c610>
after request: <sqlalchemy.orm.scoping.ScopedSession object at 0x10224c610>
bob
--------------------- >> end captured stdout << ----------------------
Run Code Online (Sandbox Code Playgroud)
根据文档,用户u不应该在获取请求后进入会话,但它是!有人知道为什么会这样吗?
此外,u.name是bob不是joe,即使请求从未提交过!(所以我确信它是同一个会议.)
作为记录,
$ pip freeze | grep Flask
Flask==0.10.1
Flask-Bcrypt==0.5.2
Flask-DebugToolbar==0.8.0
Flask-Failsafe==0.1
Flask-SQLAlchemy==0.16
Flask-Script==0.6.2
Flask-Testing==0.4
Flask-Uploads==0.1.3
Flask-WTF==0.8
Run Code Online (Sandbox Code Playgroud)
Mig*_*uel 10
我很确定混淆来自于SQLAlchemy中的会话是作用域的,这意味着每个请求处理程序都会创建并销毁自己的会话.
这是必要的,因为Web服务器可以是多线程的,因此可以同时提供多个请求,每个请求使用不同的数据库会话.
因此,您在请求上下文之外使用的会话可能与处理'/'路由的视图函数获取的会话相同,然后在最后销毁.
更新:我挖了一下,想出了这个东西.
Flask-SQLAlchemy安装了一个钩子app.teardown_appcontext,这里是它调用的地方db.session.remove().
测试环境不会完全复制实际请求的环境,因为它不会推送/弹出应用程序上下文.因此,在请求结束时永远不会删除会话.
作为一个方面说明,保持在功能登记的头脑before_request和after_request当你打电话也没有叫client.get().
您可以通过对测试进行少量更改来强制应用程序上下文推送和弹出:
def test_remove(self):
db.drop_all()
db.create_all()
u = User()
u.name = 'joe'
db.session.add(u)
db.session.commit()
with app.app_context():
client = app.test_client()
client.get('/')
print 'after request:', `db.session`
print u.name
assert u not in db.session
Run Code Online (Sandbox Code Playgroud)
通过此更改,测试通过.
Flask-Testing的文档似乎是错误的或更可能过时.也许事情就像他们在某些时候描述的那样,但这对于当前的Flask和Flask-SQLAlchemy版本来说并不准确.
我希望这有帮助!
| 归档时间: |
|
| 查看次数: |
4274 次 |
| 最近记录: |