mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
Populate docs/ from 0.65.2
This commit is contained in:
parent
ec99bb46f8
commit
264bba5db2
26 changed files with 883 additions and 5641 deletions
|
|
@ -7,7 +7,7 @@ Datasette treats SQLite database files as read-only and immutable. This means it
|
|||
|
||||
The easiest way to execute custom SQL against Datasette is through the web UI. The database index page includes a SQL editor that lets you run any SELECT query you like. You can also construct queries using the filter interface on the tables page, then click "View and edit SQL" to open that query in the custom SQL editor.
|
||||
|
||||
Note that this interface is only available if the :ref:`actions_execute_sql` permission is allowed. See :ref:`authentication_permissions_execute_sql`.
|
||||
Note that this interface is only available if the :ref:`permissions_execute_sql` permission is allowed.
|
||||
|
||||
Any Datasette SQL query is reflected in the URL of the page, allowing you to bookmark them, share them with others and navigate through previous queries using your browser back button.
|
||||
|
||||
|
|
@ -53,29 +53,22 @@ If you want to bundle some pre-written SQL queries with your Datasette-hosted da
|
|||
|
||||
The quickest way to create views is with the SQLite command-line interface::
|
||||
|
||||
sqlite3 sf-trees.db
|
||||
|
||||
::
|
||||
|
||||
$ sqlite3 sf-trees.db
|
||||
SQLite version 3.19.3 2017-06-27 16:48:08
|
||||
Enter ".help" for usage hints.
|
||||
sqlite> CREATE VIEW demo_view AS select qSpecies from Street_Tree_List;
|
||||
<CTRL+D>
|
||||
|
||||
You can also use the `sqlite-utils <https://sqlite-utils.datasette.io/>`__ tool to `create a view <https://sqlite-utils.datasette.io/en/stable/cli.html#creating-views>`__::
|
||||
|
||||
sqlite-utils create-view sf-trees.db demo_view "select qSpecies from Street_Tree_List"
|
||||
|
||||
.. _canned_queries:
|
||||
|
||||
Canned queries
|
||||
--------------
|
||||
|
||||
As an alternative to adding views to your database, you can define canned queries inside your ``datasette.yaml`` file. Here's an example:
|
||||
As an alternative to adding views to your database, you can define canned queries inside your ``metadata.json`` file. Here's an example:
|
||||
|
||||
.. [[[cog
|
||||
from metadata_doc import config_example, config_example
|
||||
config_example(cog, {
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"databases": {
|
||||
"sf-trees": {
|
||||
"queries": {
|
||||
|
|
@ -85,36 +78,7 @@ As an alternative to adding views to your database, you can define canned querie
|
|||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.. ]]]
|
||||
|
||||
.. tab:: datasette.yaml
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
databases:
|
||||
sf-trees:
|
||||
queries:
|
||||
just_species:
|
||||
sql: select qSpecies from Street_Tree_List
|
||||
|
||||
|
||||
.. tab:: datasette.json
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"databases": {
|
||||
"sf-trees": {
|
||||
"queries": {
|
||||
"just_species": {
|
||||
"sql": "select qSpecies from Street_Tree_List"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.. [[[end]]]
|
||||
}
|
||||
|
||||
Then run Datasette like this::
|
||||
|
||||
|
|
@ -147,60 +111,38 @@ Here's an example of a canned query with a named parameter:
|
|||
where neighborhood like '%' || :text || '%'
|
||||
order by neighborhood;
|
||||
|
||||
In the canned query configuration looks like this:
|
||||
In the canned query metadata (here :ref:`metadata_yaml` as ``metadata.yaml``) it looks like this:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
.. [[[cog
|
||||
config_example(cog, """
|
||||
databases:
|
||||
fixtures:
|
||||
queries:
|
||||
neighborhood_search:
|
||||
title: Search neighborhoods
|
||||
sql: |-
|
||||
select neighborhood, facet_cities.name, state
|
||||
from facetable
|
||||
join facet_cities on facetable.city_id = facet_cities.id
|
||||
where neighborhood like '%' || :text || '%'
|
||||
order by neighborhood
|
||||
""")
|
||||
.. ]]]
|
||||
title: Search neighborhoods
|
||||
|
||||
.. tab:: datasette.yaml
|
||||
Here's the equivalent using JSON (as ``metadata.json``):
|
||||
|
||||
.. code-block:: yaml
|
||||
.. code-block:: json
|
||||
|
||||
|
||||
databases:
|
||||
fixtures:
|
||||
queries:
|
||||
neighborhood_search:
|
||||
title: Search neighborhoods
|
||||
sql: |-
|
||||
select neighborhood, facet_cities.name, state
|
||||
from facetable
|
||||
join facet_cities on facetable.city_id = facet_cities.id
|
||||
where neighborhood like '%' || :text || '%'
|
||||
order by neighborhood
|
||||
|
||||
|
||||
.. tab:: datasette.json
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"databases": {
|
||||
{
|
||||
"databases": {
|
||||
"fixtures": {
|
||||
"queries": {
|
||||
"neighborhood_search": {
|
||||
"title": "Search neighborhoods",
|
||||
"sql": "select neighborhood, facet_cities.name, state\nfrom facetable\n join facet_cities on facetable.city_id = facet_cities.id\nwhere neighborhood like '%' || :text || '%'\norder by neighborhood"
|
||||
"queries": {
|
||||
"neighborhood_search": {
|
||||
"sql": "select neighborhood, facet_cities.name, state\nfrom facetable\n join facet_cities on facetable.city_id = facet_cities.id\nwhere neighborhood like '%' || :text || '%'\norder by neighborhood",
|
||||
"title": "Search neighborhoods"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.. [[[end]]]
|
||||
}
|
||||
|
||||
Note that we are using SQLite string concatenation here - the ``||`` operator - to add wildcard ``%`` characters to the string provided by the user.
|
||||
|
||||
|
|
@ -211,13 +153,12 @@ In this example the ``:text`` named parameter is automatically extracted from th
|
|||
|
||||
You can alternatively provide an explicit list of named parameters using the ``"params"`` key, like this:
|
||||
|
||||
.. [[[cog
|
||||
config_example(cog, """
|
||||
.. code-block:: yaml
|
||||
|
||||
databases:
|
||||
fixtures:
|
||||
queries:
|
||||
neighborhood_search:
|
||||
title: Search neighborhoods
|
||||
params:
|
||||
- text
|
||||
sql: |-
|
||||
|
|
@ -226,49 +167,7 @@ You can alternatively provide an explicit list of named parameters using the ``"
|
|||
join facet_cities on facetable.city_id = facet_cities.id
|
||||
where neighborhood like '%' || :text || '%'
|
||||
order by neighborhood
|
||||
""")
|
||||
.. ]]]
|
||||
|
||||
.. tab:: datasette.yaml
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
|
||||
databases:
|
||||
fixtures:
|
||||
queries:
|
||||
neighborhood_search:
|
||||
title: Search neighborhoods
|
||||
params:
|
||||
- text
|
||||
sql: |-
|
||||
select neighborhood, facet_cities.name, state
|
||||
from facetable
|
||||
join facet_cities on facetable.city_id = facet_cities.id
|
||||
where neighborhood like '%' || :text || '%'
|
||||
order by neighborhood
|
||||
|
||||
|
||||
.. tab:: datasette.json
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"databases": {
|
||||
"fixtures": {
|
||||
"queries": {
|
||||
"neighborhood_search": {
|
||||
"title": "Search neighborhoods",
|
||||
"params": [
|
||||
"text"
|
||||
],
|
||||
"sql": "select neighborhood, facet_cities.name, state\nfrom facetable\n join facet_cities on facetable.city_id = facet_cities.id\nwhere neighborhood like '%' || :text || '%'\norder by neighborhood"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.. [[[end]]]
|
||||
title: Search neighborhoods
|
||||
|
||||
.. _canned_queries_options:
|
||||
|
||||
|
|
@ -293,56 +192,21 @@ You can set a default fragment hash that will be included in the link to the can
|
|||
|
||||
This example demonstrates both ``fragment`` and ``hide_sql``:
|
||||
|
||||
.. [[[cog
|
||||
config_example(cog, """
|
||||
databases:
|
||||
fixtures:
|
||||
queries:
|
||||
neighborhood_search:
|
||||
fragment: fragment-goes-here
|
||||
hide_sql: true
|
||||
sql: |-
|
||||
select neighborhood, facet_cities.name, state
|
||||
from facetable join facet_cities on facetable.city_id = facet_cities.id
|
||||
where neighborhood like '%' || :text || '%' order by neighborhood;
|
||||
""")
|
||||
.. ]]]
|
||||
.. code-block:: json
|
||||
|
||||
.. tab:: datasette.yaml
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
|
||||
databases:
|
||||
fixtures:
|
||||
queries:
|
||||
neighborhood_search:
|
||||
fragment: fragment-goes-here
|
||||
hide_sql: true
|
||||
sql: |-
|
||||
select neighborhood, facet_cities.name, state
|
||||
from facetable join facet_cities on facetable.city_id = facet_cities.id
|
||||
where neighborhood like '%' || :text || '%' order by neighborhood;
|
||||
|
||||
|
||||
.. tab:: datasette.json
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"databases": {
|
||||
{
|
||||
"databases": {
|
||||
"fixtures": {
|
||||
"queries": {
|
||||
"neighborhood_search": {
|
||||
"fragment": "fragment-goes-here",
|
||||
"hide_sql": true,
|
||||
"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;"
|
||||
"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",
|
||||
"hide_sql": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.. [[[end]]]
|
||||
}
|
||||
|
||||
`See here <https://latest.datasette.io/fixtures#queries>`__ for a demo of this in action.
|
||||
|
||||
|
|
@ -355,132 +219,55 @@ Canned queries by default are read-only. You can use the ``"write": true`` key t
|
|||
|
||||
See :ref:`authentication_permissions_query` for details on how to add permission checks to canned queries, using the ``"allow"`` key.
|
||||
|
||||
.. [[[cog
|
||||
config_example(cog, {
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"databases": {
|
||||
"mydatabase": {
|
||||
"queries": {
|
||||
"add_name": {
|
||||
"sql": "INSERT INTO names (name) VALUES (:name)",
|
||||
"write": True
|
||||
"write": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.. ]]]
|
||||
|
||||
.. tab:: datasette.yaml
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
databases:
|
||||
mydatabase:
|
||||
queries:
|
||||
add_name:
|
||||
sql: INSERT INTO names (name) VALUES (:name)
|
||||
write: true
|
||||
|
||||
|
||||
.. tab:: datasette.json
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"databases": {
|
||||
"mydatabase": {
|
||||
"queries": {
|
||||
"add_name": {
|
||||
"sql": "INSERT INTO names (name) VALUES (:name)",
|
||||
"write": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.. [[[end]]]
|
||||
}
|
||||
|
||||
This configuration will create a page at ``/mydatabase/add_name`` displaying a form with a ``name`` field. Submitting that form will execute the configured ``INSERT`` query.
|
||||
|
||||
You can customize how Datasette represents success and errors using the following optional properties:
|
||||
|
||||
- ``on_success_message`` - the message shown when a query is successful
|
||||
- ``on_success_message_sql`` - alternative to ``on_success_message``: a SQL query that should be executed to generate the message
|
||||
- ``on_success_redirect`` - the path or URL the user is redirected to on success
|
||||
- ``on_error_message`` - the message shown when a query throws an error
|
||||
- ``on_error_redirect`` - the path or URL the user is redirected to on error
|
||||
|
||||
For example:
|
||||
|
||||
.. [[[cog
|
||||
config_example(cog, {
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"databases": {
|
||||
"mydatabase": {
|
||||
"queries": {
|
||||
"add_name": {
|
||||
"sql": "INSERT INTO names (name) VALUES (:name)",
|
||||
"params": ["name"],
|
||||
"write": True,
|
||||
"on_success_message_sql": "select 'Name inserted: ' || :name",
|
||||
"write": true,
|
||||
"on_success_message": "Name inserted",
|
||||
"on_success_redirect": "/mydatabase/names",
|
||||
"on_error_message": "Name insert failed",
|
||||
"on_error_redirect": "/mydatabase",
|
||||
"on_error_redirect": "/mydatabase"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.. ]]]
|
||||
}
|
||||
|
||||
.. tab:: datasette.yaml
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
databases:
|
||||
mydatabase:
|
||||
queries:
|
||||
add_name:
|
||||
sql: INSERT INTO names (name) VALUES (:name)
|
||||
params:
|
||||
- name
|
||||
write: true
|
||||
on_success_message_sql: 'select ''Name inserted: '' || :name'
|
||||
on_success_redirect: /mydatabase/names
|
||||
on_error_message: Name insert failed
|
||||
on_error_redirect: /mydatabase
|
||||
|
||||
|
||||
.. tab:: datasette.json
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"databases": {
|
||||
"mydatabase": {
|
||||
"queries": {
|
||||
"add_name": {
|
||||
"sql": "INSERT INTO names (name) VALUES (:name)",
|
||||
"params": [
|
||||
"name"
|
||||
],
|
||||
"write": true,
|
||||
"on_success_message_sql": "select 'Name inserted: ' || :name",
|
||||
"on_success_redirect": "/mydatabase/names",
|
||||
"on_error_message": "Name insert failed",
|
||||
"on_error_redirect": "/mydatabase"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.. [[[end]]]
|
||||
|
||||
You can use ``"params"`` to explicitly list the named parameters that should be displayed as form fields - otherwise they will be automatically detected. ``"params"`` is not necessary in the above example, since without it ``"name"`` would be automatically detected from the query.
|
||||
You can use ``"params"`` to explicitly list the named parameters that should be displayed as form fields - otherwise they will be automatically detected.
|
||||
|
||||
You can pre-populate form fields when the page first loads using a query string, e.g. ``/mydatabase/add_name?name=Prepopulated``. The user will have to submit the form to execute the query.
|
||||
|
||||
If you specify a query in ``"on_success_message_sql"``, that query will be executed after the main query. The first column of the first row return by that query will be displayed as a success message. Named parameters from the main query will be made available to the success message query as well.
|
||||
|
||||
.. _canned_queries_magic_parameters:
|
||||
|
||||
Magic parameters
|
||||
|
|
@ -513,10 +300,10 @@ Available magic parameters are:
|
|||
``_random_chars_*`` - e.g. ``_random_chars_128``
|
||||
A random string of characters of the specified length.
|
||||
|
||||
Here's an example configuration that adds a message from the authenticated user, storing various pieces of additional metadata using magic parameters:
|
||||
Here's an example configuration (this time using ``metadata.yaml`` since that provides better support for multi-line SQL queries) that adds a message from the authenticated user, storing various pieces of additional metadata using magic parameters:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
.. [[[cog
|
||||
config_example(cog, """
|
||||
databases:
|
||||
mydatabase:
|
||||
queries:
|
||||
|
|
@ -530,49 +317,6 @@ Here's an example configuration that adds a message from the authenticated user,
|
|||
:_actor_id, :message, :_now_datetime_utc
|
||||
)
|
||||
write: true
|
||||
""")
|
||||
.. ]]]
|
||||
|
||||
.. tab:: datasette.yaml
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
|
||||
databases:
|
||||
mydatabase:
|
||||
queries:
|
||||
add_message:
|
||||
allow:
|
||||
id: "*"
|
||||
sql: |-
|
||||
INSERT INTO messages (
|
||||
user_id, message, datetime
|
||||
) VALUES (
|
||||
:_actor_id, :message, :_now_datetime_utc
|
||||
)
|
||||
write: true
|
||||
|
||||
|
||||
.. tab:: datasette.json
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"databases": {
|
||||
"mydatabase": {
|
||||
"queries": {
|
||||
"add_message": {
|
||||
"allow": {
|
||||
"id": "*"
|
||||
},
|
||||
"sql": "INSERT INTO messages (\n user_id, message, datetime\n) VALUES (\n :_actor_id, :message, :_now_datetime_utc\n)",
|
||||
"write": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.. [[[end]]]
|
||||
|
||||
The form presented at ``/mydatabase/add_message`` will have just a field for ``message`` - the other parameters will be populated by the magic parameter mechanism.
|
||||
|
||||
|
|
@ -613,7 +357,7 @@ The JSON response will look like this:
|
|||
"redirect": "/data/add_name"
|
||||
}
|
||||
|
||||
The ``"message"`` and ``"redirect"`` values here will take into account ``on_success_message``, ``on_success_message_sql``, ``on_success_redirect``, ``on_error_message`` and ``on_error_redirect``, if they have been set.
|
||||
The ``"message"`` and ``"redirect"`` values here will take into account ``on_success_message``, ``on_success_redirect``, ``on_error_message`` and ``on_error_redirect``, if they have been set.
|
||||
|
||||
.. _pagination:
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue