diff --git a/datasette/templates/database.html b/datasette/templates/database.html
index 7d98f0e5..e47b2418 100644
--- a/datasette/templates/database.html
+++ b/datasette/templates/database.html
@@ -48,7 +48,7 @@
{% endif %}
{% if views %}
-
Views
+ Views
{% for view in views %}
- {{ view }}
@@ -57,10 +57,10 @@
{% endif %}
{% if queries %}
- Queries
+ Queries
{% endif %}
diff --git a/docs/sql_queries.rst b/docs/sql_queries.rst
index da10191e..c3efd930 100644
--- a/docs/sql_queries.rst
+++ b/docs/sql_queries.rst
@@ -72,7 +72,9 @@ Canned queries
--------------
As an alternative to adding views to your database, you can define canned
-queries inside your ``metadata.json`` file. Here's an example::
+queries inside your ``metadata.json`` file. Here's an example:
+
+.. code-block:: json
{
"databases": {
@@ -86,7 +88,7 @@ queries inside your ``metadata.json`` file. Here's an example::
}
}
-Then run datasette like this::
+Then run Datasette like this::
datasette sf-trees.db -m metadata.json
@@ -104,6 +106,11 @@ title and description on the canned query page. As with regular table metadata
you can alternatively specify ``"description_html"`` to have your description
rendered as HTML (rather than having HTML special characters escaped).
+.. _canned_queries_named_parameters:
+
+Named parameters
+~~~~~~~~~~~~~~~~
+
Canned queries support named parameters, so if you include those in the SQL you
will then be able to enter them using the form fields on the canned query page
or by adding them to the URL. This means canned queries can be used to create
@@ -117,7 +124,9 @@ Here's an example of a canned query with a named parameter:
from facetable join facet_cities on facetable.city_id = facet_cities.id
where neighborhood like '%' || :text || '%' order by neighborhood;
-In the canned query JSON it looks like this::
+In the canned query JSON it looks like this:
+
+.. code-block:: json
{
"databases": {
@@ -139,6 +148,31 @@ https://latest.datasette.io/fixtures/neighborhood_search?text=town
Note that we are using SQLite string concatenation here - the ``||`` operator -
to add wildcard ``%`` characters to the string provided by the user.
+.. _canned_queries_default_fragment:
+
+Setting a default fragment
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Some plugins, such as `datasette-vega `__, can be configured by including additional data in the fragment hash of the URL - the bit that comes after a ``#`` symbol.
+
+You can set a default fragment hash that will be included in the link to the canned query from the database index page using the ``"fragment"`` key:
+
+.. code-block:: json
+
+ {
+ "databases": {
+ "fixtures": {
+ "queries": {
+ "neighborhood_search": {
+ "sql": "select neighborhood, facet_cities.name, state\nfrom facetable join facet_cities on facetable.city_id = facet_cities.id\nwhere neighborhood like '%' || :text || '%' order by neighborhood;",
+ "fragment": "fragment-goes-here"
+ }
+ }
+ }
+ }
+
+`See here `__ for a demo of this in action.
+
.. _pagination:
Pagination
diff --git a/tests/fixtures.py b/tests/fixtures.py
index 0284ff9c..a3b75f9f 100644
--- a/tests/fixtures.py
+++ b/tests/fixtures.py
@@ -327,6 +327,7 @@ METADATA = {
),
"title": "Search neighborhoods",
"description_html": "Demonstrating simple like search",
+ "fragment": "fragment-goes-here",
},
},
}
diff --git a/tests/test_html.py b/tests/test_html.py
index 445f7b4c..5a07953e 100644
--- a/tests/test_html.py
+++ b/tests/test_html.py
@@ -85,6 +85,21 @@ def test_database_page_redirects_with_url_hash(app_client_with_hash):
assert "fixtures" in response.text
+def test_database_page(app_client):
+ response = app_client.get("/fixtures")
+ soup = Soup(response.body, "html.parser")
+ queries_ul = soup.find("h2", text="Queries").find_next_sibling("ul")
+ assert queries_ul is not None
+ assert [
+ (
+ "/fixtures/%F0%9D%90%9C%F0%9D%90%A2%F0%9D%90%AD%F0%9D%90%A2%F0%9D%90%9E%F0%9D%90%AC",
+ "𝐜𝐢𝐭𝐢𝐞𝐬",
+ ),
+ ("/fixtures/pragma_cache_size", "pragma_cache_size"),
+ ("/fixtures/neighborhood_search#fragment-goes-here", "Search neighborhoods"),
+ ] == [(a["href"], a.text) for a in queries_ul.find_all("a")]
+
+
def test_invalid_custom_sql(app_client):
response = app_client.get("/fixtures?sql=.schema")
assert response.status == 400