From 841cd3657618694b982f325ffb7f0ce4882071f6 Mon Sep 17 00:00:00 2001 From: Dimitris Theodorou Date: Sun, 11 Jan 2015 15:51:24 +0100 Subject: [PATCH 1/5] add basic app with raw sql alchemy --- test/basic_app_plain_sqlalchemy.py | 35 ++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 test/basic_app_plain_sqlalchemy.py diff --git a/test/basic_app_plain_sqlalchemy.py b/test/basic_app_plain_sqlalchemy.py new file mode 100644 index 0000000..43277db --- /dev/null +++ b/test/basic_app_plain_sqlalchemy.py @@ -0,0 +1,35 @@ +from flask import Flask, render_template +from flask_debugtoolbar import DebugToolbarExtension +from sqlalchemy import Column, Integer, create_engine +from sqlalchemy.orm import Session +from sqlalchemy.ext.declarative import declarative_base + +app = Flask('basic_app_plain_sqlalchemy') +app.debug = True +app.config['SECRET_KEY'] = 'abc123' + +# make sure these are printable in the config panel +app.config['BYTES_VALUE'] = b'\x00' +app.config['UNICODE_VALUE'] = u'\uffff' + + +engine = create_engine('sqlite://') +toolbar = DebugToolbarExtension(app, sqlalchemy_engine=engine) + + +Base = declarative_base() +class Foo(Base): + __tablename__ = 'foo' + id = Column(Integer, primary_key=True) + + +@app.route('/') +def index(): + Base.metadata.create_all(engine) + session = Session(engine) + session.query(Foo).filter_by(id=1).all() + return render_template('basic_app.html') + + +if __name__ == '__main__': + app.run() \ No newline at end of file From d6b782933d2ba63b08a089fa04f7035b7423b87e Mon Sep 17 00:00:00 2001 From: Dimitris Theodorou Date: Sun, 11 Jan 2015 16:11:28 +0100 Subject: [PATCH 2/5] Support raw SQL Alchemy DebugToolbar can receive an sql alchemy engine explicitly, in which case it will install engine events that record queries. Otherwise, it falls back to old Flask-SQLAlchemy behavior. --- flask_debugtoolbar/__init__.py | 18 +++++++++++++++--- flask_debugtoolbar/panels/sqlalchemy.py | 20 +++++++++++++++++++- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/flask_debugtoolbar/__init__.py b/flask_debugtoolbar/__init__.py index bf8d25f..12032ac 100644 --- a/flask_debugtoolbar/__init__.py +++ b/flask_debugtoolbar/__init__.py @@ -41,8 +41,9 @@ class DebugToolbarExtension(object): _redirect_codes = [301, 302, 303, 304] - def __init__(self, app=None): + def __init__(self, app=None, sqlalchemy_engine=None): self.app = app + self.engine = sqlalchemy_engine self.debug_toolbars = {} # Configure jinja for the internal templates and add url rules @@ -80,8 +81,19 @@ def init_app(self, app): app.add_url_rule('/_debug_toolbar/static/', '_debug_toolbar.static', self.send_static_file) - - app.register_blueprint(module, url_prefix='/_debug_toolbar/views') + if self.engine: + # use 'internal' API from flask_sqlalchemy to install events. + # maybe re-implement this for flask-debugtoolbar + from flask.ext.sqlalchemy import _EngineDebuggingSignalEvents, _record_queries + if _record_queries(app): + _EngineDebuggingSignalEvents( + engine=self.engine, + import_name=app.import_name).register() + + app.register_blueprint( + module, + url_prefix='/_debug_toolbar/views', + sqlalchemy_engine=self.engine) def _default_config(self, app): return { diff --git a/flask_debugtoolbar/panels/sqlalchemy.py b/flask_debugtoolbar/panels/sqlalchemy.py index bf421c8..3931d74 100644 --- a/flask_debugtoolbar/panels/sqlalchemy.py +++ b/flask_debugtoolbar/panels/sqlalchemy.py @@ -12,6 +12,19 @@ from flask_debugtoolbar.utils import format_fname, format_sql import itsdangerous +_engine = None + +@module.record_once +def store_engine(state): + global _engine + _engine = state.options.get('sqlalchemy_engine') + + +def get_engine(): + if _engine is not None: + return _engine + elif sqlalchemy_available: + return SQLAlchemy().get_engine(current_app) _ = lambda x: x @@ -94,6 +107,9 @@ def content(self): msg.append('') return '\n'.join(msg) + if not _engine and not sqlalchemy_available: + return 'No SQLAlchemy engine has been configured.' + queries = get_debug_queries() data = [] for query in queries: @@ -114,7 +130,9 @@ def content(self): defaults=dict(explain=True)) def sql_select(explain=False): statement, params = load_query(request.args['query']) - engine = SQLAlchemy().get_engine(current_app) + engine = get_engine() + if engine is None: + return 'No SQLAlchemy engine has been configured.' if explain: if engine.driver == 'pysqlite': From fd0df273150df1ee151b7b488b4eda5165190c60 Mon Sep 17 00:00:00 2001 From: Rene Dudfield Date: Mon, 27 Feb 2017 11:08:27 +0100 Subject: [PATCH 3/5] Correct sqlalchemy.is_available for when engine is there. --- flask_debugtoolbar/panels/sqlalchemy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flask_debugtoolbar/panels/sqlalchemy.py b/flask_debugtoolbar/panels/sqlalchemy.py index e705a39..b356436 100644 --- a/flask_debugtoolbar/panels/sqlalchemy.py +++ b/flask_debugtoolbar/panels/sqlalchemy.py @@ -73,7 +73,7 @@ def recording_enabled(): def is_available(): return (json_available and sqlalchemy_available - and extension_used() and recording_enabled()) + and (extension_used() or (_engine is not None)) and recording_enabled()) def get_queries(): From 2a6c76114c1869c5affbdb288c1a3eadc881e01c Mon Sep 17 00:00:00 2001 From: Rene Dudfield Date: Mon, 27 Feb 2017 11:16:23 +0100 Subject: [PATCH 4/5] Added docs for using Flask-SQLAlchemy-Session --- docs/panels.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/panels.rst b/docs/panels.rst index 1c9252d..a959be1 100644 --- a/docs/panels.rst +++ b/docs/panels.rst @@ -72,10 +72,14 @@ Shows SQL queries run during the current request. For additional details on query recording see the :py:func:`~flask_sqlalchemy.get_debug_queries` documentation. + If you use raw sqlalchemy with `Flask-SQLAlchemy-Session`_ pass the engine + in like DebugToolbarExtension(app, sqlalchemy_engine=engine) + + .. image:: _static/screenshot-sqlalchemy-panel.png .. _Flask-SQLAlchemy: http://flask-sqlalchemy.pocoo.org/ - +.. _Flask-SQLAlchemy-Session: https://pypi.python.org/pypi/Flask-SQLAlchemy-Session Logging ------- From 3dd4a43e97ef73fdf0fd741adadf5f3f13e386dd Mon Sep 17 00:00:00 2001 From: Rene Dudfield Date: Tue, 28 Feb 2017 10:39:16 +0100 Subject: [PATCH 5/5] Import flask_sqlalchemy instead of flask.ext.sqlalchemy. --- flask_debugtoolbar/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flask_debugtoolbar/__init__.py b/flask_debugtoolbar/__init__.py index a3f7f78..7889ae1 100644 --- a/flask_debugtoolbar/__init__.py +++ b/flask_debugtoolbar/__init__.py @@ -84,7 +84,7 @@ def init_app(self, app): if self.engine: # use 'internal' API from flask_sqlalchemy to install events. # maybe re-implement this for flask-debugtoolbar - from flask.ext.sqlalchemy import _EngineDebuggingSignalEvents, _record_queries + from flask_sqlalchemy import _EngineDebuggingSignalEvents, _record_queries if _record_queries(app): _EngineDebuggingSignalEvents( engine=self.engine,