diff --git a/.travis.yml b/.travis.yml index 0fc87d93..10666085 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,7 +27,7 @@ jobs: - npm install -g now - python tests/fixtures.py fixtures.db fixtures.json - export ALIAS=`echo $TRAVIS_COMMIT | cut -c 1-7` - - datasette publish nowv1 fixtures.db -m fixtures.json --token=$NOW_TOKEN --branch=$TRAVIS_COMMIT --version-note=$TRAVIS_COMMIT --name=datasette-latest-$ALIAS --alias=latest.datasette.io --alias=$ALIAS.datasette.io + - datasette publish nowv1 fixtures.db -m fixtures.json --token=$NOW_TOKEN --branch=$TRAVIS_COMMIT --version-note=$TRAVIS_COMMIT --name=datasette-latest-$ALIAS --alias=latest.datasette.io --alias=$ALIAS.datasette.io --extra-options='--config template_debug:1' - stage: release tagged version if: tag IS present python: 3.6 diff --git a/datasette/app.py b/datasette/app.py index 2065e356..f6b3e514 100644 --- a/datasette/app.py +++ b/datasette/app.py @@ -126,6 +126,11 @@ CONFIG_OPTIONS = ( False, "Force URLs in API output to always use https:// protocol", ), + ConfigOption( + "template_debug", + False, + "Allow display of template debug information with ?_context=1", + ), ) DEFAULT_CONFIG = {option.name: option.default for option in CONFIG_OPTIONS} diff --git a/datasette/views/base.py b/datasette/views/base.py index 5182479c..61561a32 100644 --- a/datasette/views/base.py +++ b/datasette/views/base.py @@ -1,6 +1,7 @@ import asyncio import csv import itertools +import json import re import time import urllib @@ -138,29 +139,28 @@ class BaseView(AsgiView): ) extra_template_vars.update(extra_vars) - return Response.html( - await template.render_async( - { - **context, - **{ - "app_css_hash": self.ds.app_css_hash(), - "select_templates": select_templates, - "zip": zip, - "body_scripts": body_scripts, - "extra_css_urls": self._asset_urls( - "extra_css_urls", template, context - ), - "extra_js_urls": self._asset_urls( - "extra_js_urls", template, context - ), - "format_bytes": format_bytes, - "database_url": self.database_url, - "database_color": self.database_color, - }, - **extra_template_vars, - } + template_context = { + **context, + **{ + "app_css_hash": self.ds.app_css_hash(), + "select_templates": select_templates, + "zip": zip, + "body_scripts": body_scripts, + "extra_css_urls": self._asset_urls("extra_css_urls", template, context), + "extra_js_urls": self._asset_urls("extra_js_urls", template, context), + "format_bytes": format_bytes, + "database_url": self.database_url, + "database_color": self.database_color, + }, + **extra_template_vars, + } + if request.args.get("_context") and self.ds.config("template_debug"): + return Response.html( + "
{}".format(
+ escape(json.dumps(template_context, default=repr, indent=4))
+ )
)
- )
+ return Response.html(await template.render_async(template_context))
class DataView(BaseView):
diff --git a/docs/config.rst b/docs/config.rst
index 25924593..199d9455 100644
--- a/docs/config.rst
+++ b/docs/config.rst
@@ -209,3 +209,22 @@ itself will result in new, uncachcacheed URL paths.
::
datasette mydatabase.db --config hash_urls:1
+
+.. _config_template_debug:
+
+template_debug
+--------------
+
+This setting enables template context debug mode, which is useful to help understand what variables are available to custom templates when you are writing them.
+
+Enable it like this::
+
+ datasette mydatabase.db --config template_debug:1
+
+Now you can add ``?_context=1`` or ``&_context=1`` to any Datasette page to see the context that was passed to that template.
+
+Some examples:
+
+* https://latest.datasette.io/?_context=1
+* https://latest.datasette.io/fixtures?_context=1
+* https://latest.datasette.io/fixtures/roadside_attractions?_context=1
diff --git a/tests/test_api.py b/tests/test_api.py
index cf09c1ba..979ee9bf 100644
--- a/tests/test_api.py
+++ b/tests/test_api.py
@@ -1287,6 +1287,7 @@ def test_config_json(app_client):
"truncate_cells_html": 2048,
"force_https_urls": False,
"hash_urls": False,
+ "template_debug": False,
} == response.json
diff --git a/tests/test_html.py b/tests/test_html.py
index db73da18..823d7c9a 100644
--- a/tests/test_html.py
+++ b/tests/test_html.py
@@ -1073,3 +1073,16 @@ def test_zero_results(app_client, path):
soup = Soup(response.text, "html.parser")
assert 0 == len(soup.select("table"))
assert 1 == len(soup.select("p.zero-results"))
+
+
+def test_config_template_debug_on():
+ for client in make_app_client(config={"template_debug": True}):
+ response = client.get("/fixtures/facetable?_context=1")
+ assert response.status == 200
+ assert response.text.startswith("{")
+
+
+def test_config_template_debug_off(app_client):
+ response = app_client.get("/fixtures/facetable?_context=1")
+ assert response.status == 200
+ assert not response.text.startswith("{")