2018-04-20 14:32:02 +00:00
.. _plugins:
2018-04-16 15:12:09 +00:00
Plugins
=======
2019-05-16 05:18:02 +00:00
Datasette's plugin system allows additional features to be implemented as Python
code (or front-end JavaScript) which can be wrapped up in a separate Python
package. The underlying mechanism uses `pluggy <https://pluggy.readthedocs.io/> `_ .
2018-04-16 15:12:09 +00:00
2021-01-09 22:17:18 +00:00
See the `Datasette plugins directory <https://datasette.io/plugins> `__ for a list of existing plugins, or take a look at the
2019-11-27 19:19:11 +00:00
`datasette-plugin <https://github.com/topics/datasette-plugin> `__ topic on GitHub.
Things you can do with plugins include:
* Add visualizations to Datasette, for example
`datasette-cluster-map <https://github.com/simonw/datasette-cluster-map> `__ and
`datasette-vega <https://github.com/simonw/datasette-vega> `__ .
* Make new custom SQL functions available for use within Datasette, for example
`datasette-haversine <https://github.com/simonw/datasette-haversine> `__ and
`datasette-jellyfish <https://github.com/simonw/datasette-jellyfish> `__ .
2020-06-05 03:10:40 +00:00
* Define custom output formats with custom extensions, for example `datasette-atom <https://github.com/simonw/datasette-atom> `__ and
`datasette-ics <https://github.com/simonw/datasette-ics> `__ .
2019-11-27 19:19:11 +00:00
* Add template functions that can be called within your Jinja custom templates,
for example `datasette-render-markdown <https://github.com/simonw/datasette-render-markdown#markdown-in-templates> `__ .
* Customize how database values are rendered in the Datasette interface, for example
`datasette-render-binary <https://github.com/simonw/datasette-render-binary> `__ and
`datasette-pretty-json <https://github.com/simonw/datasette-pretty-json> `__ .
2022-12-30 14:01:39 +00:00
* Customize how Datasette's authentication and permissions systems work, for example `datasette-auth-passwords <https://github.com/simonw/datasette-auth-passwords> `__ and
2020-06-12 00:43:51 +00:00
`datasette-permissions-sql <https://github.com/simonw/datasette-permissions-sql> `__ .
2019-11-27 19:19:11 +00:00
2020-04-27 16:30:24 +00:00
.. _plugins_installing:
Installing plugins
------------------
2018-04-16 15:12:09 +00:00
2020-06-22 02:37:48 +00:00
If a plugin has been packaged for distribution using setuptools you can use the plugin by installing it alongside Datasette in the same virtual environment or Docker container.
2018-04-16 15:12:09 +00:00
2020-08-11 22:31:47 +00:00
You can install plugins using the `` datasette install `` command::
datasette install datasette-vega
You can uninstall plugins with `` datasette uninstall `` ::
datasette uninstall datasette-vega
2020-08-19 17:20:41 +00:00
You can upgrade plugins with `` datasette install --upgrade `` or `` datasette install -U `` ::
datasette install -U datasette-vega
This command can also be used to upgrade Datasette itself to the latest released version::
datasette install -U datasette
2023-03-06 22:27:30 +00:00
You can install multiple plugins at once by listing them as lines in a `` requirements.txt `` file like this::
datasette-vega
datasette-cluster-map
Then pass that file to `` datasette install -r `` ::
datasette install -r requirements.txt
The `` install `` and `` uninstall `` commands are thin wrappers around `` pip install `` and `` pip uninstall `` , which ensure that they run `` pip `` in the same virtual environment as Datasette itself.
2020-08-11 22:31:47 +00:00
One-off plugins using --plugins-dir
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2020-06-22 02:37:48 +00:00
You can also define one-off per-project plugins by saving them as `` plugin_name.py `` functions in a `` plugins/ `` folder and then passing that folder to `` datasette `` using the `` --plugins-dir `` option::
2018-04-16 15:12:09 +00:00
2020-06-22 02:37:48 +00:00
datasette mydb.db --plugins-dir=plugins/
2018-04-18 15:05:06 +00:00
2020-08-11 22:31:47 +00:00
Deploying plugins using datasette publish
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2020-06-22 02:37:48 +00:00
The `` datasette publish `` and `` datasette package `` commands both take an optional `` --install `` argument. You can use this one or more times to tell Datasette to `` pip install `` specific plugins as part of the process::
2018-04-16 15:12:09 +00:00
2020-06-22 02:37:48 +00:00
datasette publish cloudrun mydb.db --install=datasette-vega
2018-04-16 15:12:09 +00:00
2020-06-22 02:37:48 +00:00
You can use the name of a package on PyPI or any of the other valid arguments to `` pip install `` such as a URL to a `` .zip `` file::
2018-04-16 15:12:09 +00:00
2020-06-22 02:37:48 +00:00
datasette publish cloudrun mydb.db \
--install=https://url-to-my-package.zip
2018-04-16 15:12:09 +00:00
2023-08-30 22:12:24 +00:00
.. _plugins_datasette_load_plugins:
Controlling which plugins are loaded
------------------------------------
Datasette defaults to loading every plugin that is installed in the same virtual environment as Datasette itself.
You can set the `` DATASETTE_LOAD_PLUGINS `` environment variable to a comma-separated list of plugin names to load a controlled subset of plugins instead.
For example, to load just the `` datasette-vega `` and `` datasette-cluster-map `` plugins, set `` DATASETTE_LOAD_PLUGINS `` to `` datasette-vega,datasette-cluster-map `` :
.. code-block :: bash
export DATASETTE_LOAD_PLUGINS='datasette-vega,datasette-cluster-map'
datasette mydb.db
Or:
.. code-block :: bash
DATASETTE_LOAD_PLUGINS='datasette-vega,datasette-cluster-map' \
datasette mydb.db
To disable the loading of all additional plugins, set `` DATASETTE_LOAD_PLUGINS `` to an empty string:
.. code-block :: bash
export DATASETTE_LOAD_PLUGINS=''
datasette mydb.db
A quick way to test this setting is to use it with the `` datasette plugins `` command:
.. code-block :: bash
DATASETTE_LOAD_PLUGINS='datasette-vega' datasette plugins
This should output the following:
.. code-block :: json
[
{
"name": "datasette-vega",
"static": true,
"templates": false,
"version": "0.6.2",
"hooks": [
"extra_css_urls",
"extra_js_urls"
]
}
]
2019-02-01 03:47:05 +00:00
.. _plugins_installed:
2019-01-26 20:01:16 +00:00
Seeing what plugins are installed
---------------------------------
You can see a list of installed plugins by navigating to the `` /-/plugins `` page of your Datasette instance - for example: https://fivethirtyeight.datasettes.com/-/plugins
You can also use the `` datasette plugins `` command::
2023-08-09 22:04:16 +00:00
datasette plugins
Which outputs:
.. code-block :: json
2019-01-26 20:01:16 +00:00
[
{
"name": "datasette_json_html",
"static": false,
"templates": false,
"version": "0.4.0"
}
]
2022-01-20 05:04:09 +00:00
.. [[[cog
from datasette import cli
from click.testing import CliRunner
import textwrap, json
cog.out("\n")
result = CliRunner().invoke(cli.cli, ["plugins", "--all"])
# cog.out() with text containing newlines was unindenting for some reason
2023-08-09 22:04:16 +00:00
cog.outl("If you run `` datasette plugins --all `` it will include default plugins that ship as part of Datasette:\n")
cog.outl(".. code-block:: json\n")
2022-01-20 05:04:09 +00:00
plugins = [p for p in json.loads(result.output) if p["name"].startswith("datasette.")]
indented = textwrap.indent(json.dumps(plugins, indent=4), " ")
for line in indented.split("\n"):
cog.outl(line)
cog.out("\n\n")
.. ]]]
2023-08-09 22:04:16 +00:00
If you run `` datasette plugins --all `` it will include default plugins that ship as part of Datasette:
.. code-block :: json
2019-01-26 20:01:16 +00:00
[
2022-01-20 05:04:09 +00:00
{
2022-01-20 05:14:04 +00:00
"name": "datasette.actor_auth_cookie",
2022-01-20 05:04:09 +00:00
"static": false,
"templates": false,
"version": null,
"hooks": [
2022-01-20 05:14:04 +00:00
"actor_from_request"
2022-01-20 05:04:09 +00:00
]
},
2019-01-26 20:01:16 +00:00
{
2022-01-20 05:14:04 +00:00
"name": "datasette.blob_renderer",
2019-01-26 20:01:16 +00:00
"static": false,
"templates": false,
2022-01-20 05:04:09 +00:00
"version": null,
"hooks": [
2022-01-20 05:14:04 +00:00
"register_output_renderer"
2022-01-20 05:04:09 +00:00
]
2019-01-26 20:01:16 +00:00
},
{
2022-01-20 05:14:04 +00:00
"name": "datasette.default_magic_parameters",
2022-01-20 05:04:09 +00:00
"static": false,
"templates": false,
"version": null,
"hooks": [
2022-01-20 05:14:04 +00:00
"register_magic_parameters"
2022-01-20 05:04:09 +00:00
]
},
{
2022-01-20 05:14:04 +00:00
"name": "datasette.default_menu_links",
2020-04-04 23:04:33 +00:00
"static": false,
"templates": false,
2022-01-20 05:04:09 +00:00
"version": null,
"hooks": [
2022-01-20 05:14:04 +00:00
"menu_links"
2022-01-20 05:04:09 +00:00
]
2020-04-04 23:04:33 +00:00
},
{
2022-01-20 05:14:04 +00:00
"name": "datasette.default_permissions",
2019-01-26 20:01:16 +00:00
"static": false,
"templates": false,
2022-01-20 05:04:09 +00:00
"version": null,
"hooks": [
2022-10-26 02:55:47 +00:00
"actor_from_request",
2022-10-26 04:26:12 +00:00
"permission_allowed",
2022-12-13 02:05:54 +00:00
"register_permissions",
2022-10-30 21:53:33 +00:00
"skip_csrf"
2022-01-20 05:04:09 +00:00
]
2019-01-26 20:01:16 +00:00
},
2024-01-31 23:21:40 +00:00
{
"name": "datasette.events",
"static": false,
"templates": false,
"version": null,
"hooks": [
"register_events"
]
},
2019-01-26 20:01:16 +00:00
{
2022-01-20 05:14:04 +00:00
"name": "datasette.facets",
2022-01-20 05:04:09 +00:00
"static": false,
"templates": false,
"version": null,
"hooks": [
2022-01-20 05:14:04 +00:00
"register_facet_classes"
2022-01-20 05:04:09 +00:00
]
},
{
2022-01-20 05:14:04 +00:00
"name": "datasette.filters",
2019-01-26 20:01:16 +00:00
"static": false,
"templates": false,
2022-01-20 05:04:09 +00:00
"version": null,
"hooks": [
2022-01-20 05:14:04 +00:00
"filters_from_request"
2022-01-20 05:04:09 +00:00
]
},
2022-07-18 00:57:41 +00:00
{
"name": "datasette.forbidden",
"static": false,
"templates": false,
"version": null,
"hooks": [
"forbidden"
]
},
{
"name": "datasette.handle_exception",
"static": false,
"templates": false,
"version": null,
"hooks": [
"handle_exception"
]
},
2022-01-20 05:04:09 +00:00
{
2022-01-20 05:14:04 +00:00
"name": "datasette.publish.cloudrun",
2022-01-20 05:04:09 +00:00
"static": false,
"templates": false,
"version": null,
"hooks": [
2022-01-20 05:14:04 +00:00
"publish_subcommand"
2022-01-20 05:04:09 +00:00
]
},
{
2022-01-20 05:14:04 +00:00
"name": "datasette.publish.heroku",
2022-01-20 05:04:09 +00:00
"static": false,
"templates": false,
"version": null,
"hooks": [
2022-01-20 05:14:04 +00:00
"publish_subcommand"
2022-01-20 05:04:09 +00:00
]
},
{
2022-01-20 05:14:04 +00:00
"name": "datasette.sql_functions",
2022-01-20 05:04:09 +00:00
"static": false,
"templates": false,
"version": null,
"hooks": [
2022-01-20 05:14:04 +00:00
"prepare_connection"
2022-01-20 05:04:09 +00:00
]
2019-01-26 20:01:16 +00:00
}
]
2022-01-20 05:04:09 +00:00
.. [[[end]]]
2019-01-26 20:01:16 +00:00
You can add the `` --plugins-dir= `` option to include any plugins found in that directory.
2023-08-09 22:04:16 +00:00
Add `` --requirements `` to output a list of installed plugins that can then be installed in another Datasette instance using `` datasette install -r requirements.txt `` ::
datasette plugins --requirements
The output will look something like this::
datasette-codespaces==0.1.1
datasette-graphql==2.2
datasette-json-html==1.0.1
datasette-pretty-json==0.2.2
datasette-x-forwarded-host==0.1
To write that to a `` requirements.txt `` file, run this::
datasette plugins --requirements > requirements.txt
2018-09-19 17:48:12 +00:00
.. _plugins_configuration:
2018-08-28 08:35:21 +00:00
Plugin configuration
--------------------
2024-02-01 04:03:19 +00:00
Plugins can have their own configuration, embedded in a :ref: `configuration file <configuration>` . Configuration options for plugins live within a `` "plugins" `` key in that file, which can be included at the root, database or table level.
2018-08-28 08:35:21 +00:00
2020-11-15 16:43:13 +00:00
Here is an example of some plugin configuration for a specific table:
2023-07-08 18:00:08 +00:00
.. [[[cog
2023-10-12 16:16:37 +00:00
from metadata_doc import config_example
config_example(cog, {
2020-11-15 16:45:26 +00:00
"databases": {
2018-08-28 08:35:21 +00:00
"sf-trees": {
"tables": {
"Street_Tree_List": {
"plugins": {
"datasette-cluster-map": {
"latitude_column": "lat",
"longitude_column": "lng"
}
}
}
}
}
}
2023-07-08 18:00:08 +00:00
})
.. ]]]
2023-10-12 16:16:37 +00:00
.. tab :: datasette.yaml
2023-07-08 18:00:08 +00:00
.. code-block :: yaml
databases:
sf-trees:
tables:
Street_Tree_List:
plugins:
datasette-cluster-map:
latitude_column: lat
longitude_column: lng
2023-10-12 16:16:37 +00:00
.. tab :: datasette.json
2023-07-08 18:00:08 +00:00
.. code-block :: json
{
"databases": {
"sf-trees": {
"tables": {
"Street_Tree_List": {
"plugins": {
"datasette-cluster-map": {
"latitude_column": "lat",
"longitude_column": "lng"
}
}
}
}
}
}
}
.. [[[end]]]
2018-08-28 08:35:21 +00:00
This tells the `` datasette-cluster-map `` column which latitude and longitude columns should be used for a table called `` Street_Tree_List `` inside a database file called `` sf-trees.db `` .
2019-07-08 02:06:31 +00:00
.. _plugins_configuration_secret:
2019-07-04 05:36:44 +00:00
Secret configuration values
~~~~~~~~~~~~~~~~~~~~~~~~~~~
2023-10-12 16:16:37 +00:00
Some plugins may need configuration that should stay secret - API keys for example. There are two ways in which you can store secret configuration values.
2019-07-04 05:36:44 +00:00
2020-11-15 16:43:13 +00:00
**As environment variables** . If your secret lives in an environment variable that is available to the Datasette process, you can indicate that the configuration value should be read from that environment variable like so:
2023-07-08 18:00:08 +00:00
.. [[[cog
2023-10-12 16:16:37 +00:00
config_example(cog, {
2019-07-04 05:36:44 +00:00
"plugins": {
"datasette-auth-github": {
"client_secret": {
"$env": "GITHUB_CLIENT_SECRET"
}
}
}
2023-07-08 18:00:08 +00:00
})
.. ]]]
2019-07-04 05:36:44 +00:00
2023-10-12 16:16:37 +00:00
.. tab :: datasette.yaml
2023-07-08 18:00:08 +00:00
.. code-block :: yaml
plugins:
datasette-auth-github:
client_secret:
$env: GITHUB_CLIENT_SECRET
2023-10-12 16:16:37 +00:00
.. tab :: datasette.json
2023-07-08 18:00:08 +00:00
.. code-block :: json
{
"plugins": {
"datasette-auth-github": {
"client_secret": {
"$env": "GITHUB_CLIENT_SECRET"
}
}
}
}
.. [[[end]]]
2020-11-15 16:43:13 +00:00
2023-07-08 18:00:08 +00:00
**As values in separate files** . Your secrets can also live in files on disk. To specify a secret should be read from a file, provide the full file path like this:
2019-07-04 05:36:44 +00:00
2023-07-08 18:00:08 +00:00
.. [[[cog
2023-10-12 16:16:37 +00:00
config_example(cog, {
2019-07-04 05:36:44 +00:00
"plugins": {
"datasette-auth-github": {
"client_secret": {
"$file": "/secrets/client-secret"
}
}
}
2023-07-08 18:00:08 +00:00
})
.. ]]]
2023-10-12 16:16:37 +00:00
.. tab :: datasette.yaml
2023-07-08 18:00:08 +00:00
.. code-block :: yaml
plugins:
datasette-auth-github:
client_secret:
$file: /secrets/client-secret
2023-10-12 16:16:37 +00:00
.. tab :: datasette.json
2023-07-08 18:00:08 +00:00
.. code-block :: json
{
"plugins": {
"datasette-auth-github": {
"client_secret": {
"$file": "/secrets/client-secret"
}
}
}
}
.. [[[end]]]
2019-07-04 05:36:44 +00:00
2019-07-08 02:06:31 +00:00
If you are publishing your data using the :ref: `datasette publish <cli_publish>` family of commands, you can use the `` --plugin-secret `` option to set these secrets at publish time. For example, using Heroku you might run the following command::
2023-08-09 22:04:16 +00:00
datasette publish heroku my_database.db \
2019-07-08 02:06:31 +00:00
--name my-heroku-app-demo \
--install=datasette-auth-github \
--plugin-secret datasette-auth-github client_id your_client_id \
--plugin-secret datasette-auth-github client_secret your_client_secret
2020-11-15 16:43:13 +00:00
2023-07-08 18:00:08 +00:00
This will set the necessary environment variables and add the following to the deployed `` metadata.yaml `` :
2020-11-15 16:43:13 +00:00
2023-07-08 18:00:08 +00:00
.. [[[cog
2023-10-12 16:16:37 +00:00
config_example(cog, {
2020-11-15 16:43:13 +00:00
"plugins": {
"datasette-auth-github": {
"client_id": {
"$env": "DATASETTE_AUTH_GITHUB_CLIENT_ID"
},
"client_secret": {
"$env": "DATASETTE_AUTH_GITHUB_CLIENT_SECRET"
}
}
}
2023-07-08 18:00:08 +00:00
})
.. ]]]
2023-10-12 16:16:37 +00:00
.. tab :: datasette.yaml
2023-07-08 18:00:08 +00:00
.. code-block :: yaml
plugins:
datasette-auth-github:
client_id:
$env: DATASETTE_AUTH_GITHUB_CLIENT_ID
client_secret:
$env: DATASETTE_AUTH_GITHUB_CLIENT_SECRET
2023-10-12 16:16:37 +00:00
.. tab :: datasette.json
2023-07-08 18:00:08 +00:00
.. code-block :: json
{
"plugins": {
"datasette-auth-github": {
"client_id": {
"$env": "DATASETTE_AUTH_GITHUB_CLIENT_ID"
},
"client_secret": {
"$env": "DATASETTE_AUTH_GITHUB_CLIENT_SECRET"
}
}
}
}
.. [[[end]]]