现在非常沮丧。我有这个问题,使用类类型(即User.query.filter(...)
或类本身的实例(即u = User(...)
; return u.query.filter(...).first()
)执行数据库查询会导致每次创建一个新会话
最后,当我尝试执行添加/提交时,我得到了谚语:
InvalidRequestError: Object '<Loadable at 0x1b02f90>' is already attached to session '1' (this is '4')
对于它的价值,我发现新的会话继续由以下原因创建:
app/_ _ init _ _.py:
@login_manager.user_loader
def load_user(id):
from app.users.models import User
return User.query.get(int(id))
所有页面请求都会调用load_user()
,每次点击时,我都会有一个新会话。我可以自信地这样说,因为我在中设置了断点
/lib/python2.7/site-packages/sqlalchemy/orm/session.py
用于创建和销毁会话。我希望它有点小,可以指出我对如何分配这些东西的严重误解。我开始一整天的头发,但是我已经在这一个上刮了很长时间,因为我已经秃了。请保存我的头发。
因此,采取Miguel的建议并在会话创建地点设置断点
lib/python2.7/site-packages/flask_sqlalchemy/__init__.py(137)__init__()
我能够看到它是我编写的一个函数的结果,它逐个加载它在给定目录中看到的所有模块。下面的堆栈跟踪:
/home/robert/snak2/run.py(1)<module>()
-> from app import app
/home/robert/snak2/app/__init__.py(39)<module>()
-> load_all_modules_from_dir('app')
/home/robert/snak2/app/utils.py(87)load_all_modules_from_dir()
-> ).load_module(full_package_name)
/usr/lib64/python2.7/pkgutil.py(246)load_module()
-> mod = imp.load_module(fullname, self.file, self.filename, self.etc)
/home/robert/snak2/app/account/__init__.py(17)<module>()
-> mod.mod_register(MODNAME, MODCAT, NAME, LINK, AUTHOR, DESC, ICON, NAVS)
/home/robert/snak2/app/loader.py(159)mod_register()
**-> mod = Loadable.query.filter(Loadable.modname == modname).first()(**)**
/home/robert/snak2/env/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py(429)__get__()
-> return type.query_class(mapper, session=self.sa.session())
/home/robert/snak2/env/lib/python2.7/site-packages/sqlalchemy/orm/scoping.py(70)__call__()
-> return self.registry()
/home/robert/snak2/env/lib/python2.7/site-packages/sqlalchemy/util/_collections.py(864)__call__()
-> return self.registry.setdefault(key, self.createfunc())
> /home/robert/snak2/env/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py(137)__init__()
-> self.app = db.get_app()
基于Miguel在他的kick教程中给出的信息,我相信它是用(**)表示的堆栈中的行实际上导致创建一个新会话(并且持久化)。但是如何让它消失呢?