-
Notifications
You must be signed in to change notification settings - Fork 4
/
flask_sqlalchemy_session.py
71 lines (55 loc) · 2.25 KB
/
flask_sqlalchemy_session.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
"""
Flask-SQLAlchemy-Session
-----------------------
Provides an SQLAlchemy scoped session that creates
unique sessions per Flask request
Forked from: https://github.com/dtheodor/flask-sqlalchemy-session
Because of these unresolved issues:
https://github.com/dtheodor/flask-sqlalchemy-session/issues/16
https://github.com/dtheodor/flask-sqlalchemy-session/issues/14
That were preventing us from updating flask and werkzeug.
These PRs have been applied to fix the noted issues:
https://github.com/dtheodor/flask-sqlalchemy-session/pull/17
https://github.com/dtheodor/flask-sqlalchemy-session/pull/15
"""
from flask import current_app
from sqlalchemy.orm import scoped_session
from werkzeug.local import LocalProxy
def _get_session():
app = current_app._get_current_object()
if not hasattr(app, "scoped_session"):
raise AttributeError(
"{} has no 'scoped_session' attribute. You need to initialize it "
"with a flask_scoped_session.".format(app)
)
return app.scoped_session
current_session = LocalProxy(_get_session)
"""Provides the current SQL Alchemy session within a request.
Will raise an exception if no :data:`~flask.current_app` is available or it has
not been initialized with a :class:`flask_scoped_session`
"""
class flask_scoped_session(scoped_session):
"""A :class:`~sqlalchemy.orm.scoping.scoped_session` whose scope is set to
the Flask application context.
"""
def __init__(self, session_factory, app=None):
"""
:param session_factory: A callable that returns a
:class:`~sqlalchemy.orm.session.Session`
:param app: a :class:`~flask.Flask` application
"""
try:
from greenlet import getcurrent as scopefunc
except ImportError:
from threading import get_ident as scopefunc
super().__init__(session_factory, scopefunc=scopefunc)
if app is not None:
self.init_app(app)
def init_app(self, app):
"""Setup scoped session creation and teardown for the passed ``app``.
:param app: a :class:`~flask.Flask` application
"""
app.scoped_session = self
@app.teardown_appcontext
def remove_scoped_session(*args, **kwargs):
app.scoped_session.remove()