mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
Mechanism for adding a default URL fragment to a canned query
Closes #767
This commit is contained in:
parent
af5702220c
commit
ad88c9b3f3
4 changed files with 56 additions and 6 deletions
|
|
@ -48,7 +48,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if views %}
|
{% if views %}
|
||||||
<h2>Views</h2>
|
<h2 id="views">Views</h2>
|
||||||
<ul>
|
<ul>
|
||||||
{% for view in views %}
|
{% for view in views %}
|
||||||
<li><a href="{{ database_url(database) }}/{{ view|urlencode }}">{{ view }}</a></li>
|
<li><a href="{{ database_url(database) }}/{{ view|urlencode }}">{{ view }}</a></li>
|
||||||
|
|
@ -57,10 +57,10 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if queries %}
|
{% if queries %}
|
||||||
<h2>Queries</h2>
|
<h2 id="queries">Queries</h2>
|
||||||
<ul>
|
<ul>
|
||||||
{% for query in queries %}
|
{% for query in queries %}
|
||||||
<li><a href="{{ database_url(database) }}/{{ query.name|urlencode }}" title="{{ query.description or query.sql }}">{{ query.title or query.name }}</a></li>
|
<li><a href="{{ database_url(database) }}/{{ query.name|urlencode }}{% if query.fragment %}#{{ query.fragment }}{% endif %}" title="{{ query.description or query.sql }}">{{ query.title or query.name }}</a></li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,9 @@ Canned queries
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
As an alternative to adding views to your database, you can define canned
|
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": {
|
"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
|
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
|
you can alternatively specify ``"description_html"`` to have your description
|
||||||
rendered as HTML (rather than having HTML special characters escaped).
|
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
|
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
|
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
|
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
|
from facetable join facet_cities on facetable.city_id = facet_cities.id
|
||||||
where neighborhood like '%' || :text || '%' order by neighborhood;
|
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": {
|
"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 -
|
Note that we are using SQLite string concatenation here - the ``||`` operator -
|
||||||
to add wildcard ``%`` characters to the string provided by the user.
|
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 <https://github.com/simonw/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 <https://latest.datasette.io/fixtures#queries>`__ for a demo of this in action.
|
||||||
|
|
||||||
.. _pagination:
|
.. _pagination:
|
||||||
|
|
||||||
Pagination
|
Pagination
|
||||||
|
|
|
||||||
|
|
@ -327,6 +327,7 @@ METADATA = {
|
||||||
),
|
),
|
||||||
"title": "Search neighborhoods",
|
"title": "Search neighborhoods",
|
||||||
"description_html": "<b>Demonstrating</b> simple like search",
|
"description_html": "<b>Demonstrating</b> simple like search",
|
||||||
|
"fragment": "fragment-goes-here",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,21 @@ def test_database_page_redirects_with_url_hash(app_client_with_hash):
|
||||||
assert "fixtures" in response.text
|
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):
|
def test_invalid_custom_sql(app_client):
|
||||||
response = app_client.get("/fixtures?sql=.schema")
|
response = app_client.get("/fixtures?sql=.schema")
|
||||||
assert response.status == 400
|
assert response.status == 400
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue