Open jeffwidman opened 8 years ago
Jef did you have any luck getting this done?
No. The way to do it I think, so you don't have to get funky with adding a HTML wrapper around the JSON is detect the content type and have the toolbar append its own bit of JSON with the sqlalchemy queries + page timing info, but thats still a pain methinks compared to just manually setting sqlalchemy to echo queries to stdout and watching your logs as you hit various endpoints.
Thanks Jeff.
Workaround:
@app.after_request
def after_request(response):
# Wrap JSON responses by HTML and ask flask-debugtoolbar to inject own HTML into it
if app.config.get("DEBUG_TB_ENABLED", False) and response.mimetype == "application/json" and response.status_code != 401:
response.direct_passthrough = False # Work-around for profiling of streamed JSON data download
args = dict(response=response.data.decode("utf-8"), http_code=response.status)
html_wrapped_response = make_response(render_template("wrap_json.html", **args), response.status_code)
response = app.extensions["debugtoolbar"].process_response(html_wrapped_response)
return response
and
<html>
<head>
<title>JSON Response</title>
</head>
<body>
<h1>HTML Wrapper for JSON Response</h1>
<h2>HTTP Code</h2>
<pre>{{ http_code }}</pre>
<h2>JSON Response</h2>
<pre>{{ response }}</pre>
</body>
</html>
I also had to init the FDT like the following to make the above snippet work instead of just
DebugToolbarExtension(app)
app.extensions = getattr(app, 'extensions', {})
app.extensions['debugtoolbar'] = DebugToolbarExtension(app)
@sarimak I add code exactly as yours, the toolbar show up on the page, but nothing pop up when click the menus. I compared all the requests to the example in the source, there are two toolbar.css requests send to server, the rest requests are totally same.
@guyecode You're right, FDT has changed since I posted the workaround. I can reproduce the issue (FDT for JSON response is displayed but ignores click events -- while it works fine for HTML response) with the following code:
import flask
import flask_debugtoolbar
app = flask.Flask('test', template_folder='.')
app.config['DEBUG_TB_ENABLED'] = True
app.config['SECRET_KEY'] = '123'
toolbar = flask_debugtoolbar.DebugToolbarExtension(app)
@app.after_request
def after_request(response):
if response.mimetype == "application/json":
html_wrapped_response = flask.make_response(flask.render_template("wrap_json.html", response=response.data.decode("utf-8"), http_code=response.status), response.status_code)
return toolbar.process_response(html_wrapped_response)
return response
@app.route('/json')
def test_json():
return flask.jsonify(dict(key1='value1')), 200
@app.route('/html')
def test_html():
return '<head/><body>test</body>', 200
if __name__ == '__main__':
app.run(debug=True)
Unfortunately, I am not skilled enough in JavaScript to troubleshoot the issue.
@sarimak
modify wrap_json.html to:
<html>
<head>
<title>JSON Response</title>
</head>
<body>
<h1>HTML Wrapper for JSON Response</h1>
<h2>HTTP Code</h2>
<pre>{{ http_code }}</pre>
<h2>JSON Response</h2>
<pre>{{ response }}</pre>
</body>
<script>
$('#flDebugPanelList').find('li a').click(function () {
const current = $('#flDebug #' + this.className + '-content');
if (current.is(':visible')) {
$(document).trigger('close.flDebug');
$(this).parent().removeClass('active');
} else {
$('.panelContent').hide();
current.show();
$('#flDebugToolbar').find('li').removeClass('active');
$(this).parent().addClass('active');
}
});
</script>
</html>
I was also having issues with the click events not working with If you create the after_request before the toolbar extension it will see the html mimetype and work without needing future changes. Here's an extension I wrote for this in my app.
"""Flask Extensions"""
import flask
import flask_debugtoolbar
class DevToolbar:
"""Add debug toolbars with json to html
Note you must pass `_debug` param to convert the json response
"""
def __init__(self, app):
wrap_json = """
<html>
<head>
<title>Debugging JSON Response</title>
</head>
<body>
<h1>Wrapped JSON Response</h1>
<h2>HTTP Code</h2>
<pre>{{ http_code }}</pre>
<h2>JSON Response</h2>
<pre>{{ response }}</pre>
</body>
</html>
"""
@app.after_request
def after_request(response):
if response.mimetype == "application/json" and \
'_debug' in flask.request.args:
html_wrapped_response = flask.make_response(
flask.render_template_string(
wrap_json,
response=response.data.decode("utf-8"),
http_code=response.status
),
response.status_code,
)
return app.process_response(html_wrapped_response)
return response
flask_debugtoolbar.DebugToolbarExtension(app)
I am debugging a Flask app that serves up JSON for an API endpoint.
I'm viewing the JSON in the browser, and it'd be convenient to display the toolbar as well.
My understanding of content types is a little hazy... is it possible to add an option to display the toolbar alongside this JSON? Like perhaps a config setting that lets me turn on the toolbar for all responses, not just with
<! doctype html>
?