Skip to content

Commit

Permalink
Rearrange plugin hooks page with more sections, closes #2300
Browse files Browse the repository at this point in the history
  • Loading branch information
simonw committed Mar 12, 2024
1 parent 06281a0 commit 7339cc5
Showing 1 changed file with 93 additions and 79 deletions.
172 changes: 93 additions & 79 deletions docs/plugin_hooks.rst
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,17 @@ This function can return an awaitable function if it needs to run any async code

Examples: `datasette-edit-templates <https://datasette.io/plugins/datasette-edit-templates>`_

.. _plugin_page_extras:

Page extras
-----------

These plugin hooks can be used to affect the way HTML pages for different Datasette interfaces are rendered.

.. _plugin_hook_extra_template_vars:

extra_template_vars(template, database, table, columns, view_name, request, datasette)
--------------------------------------------------------------------------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Extra template variables that should be made available in the rendered template context.

Expand Down Expand Up @@ -184,7 +191,7 @@ Examples: `datasette-search-all <https://datasette.io/plugins/datasette-search-a
.. _plugin_hook_extra_css_urls:

extra_css_urls(template, database, table, columns, view_name, request, datasette)
---------------------------------------------------------------------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This takes the same arguments as :ref:`extra_template_vars(...) <plugin_hook_extra_template_vars>`

Expand Down Expand Up @@ -238,7 +245,7 @@ Examples: `datasette-cluster-map <https://datasette.io/plugins/datasette-cluster
.. _plugin_hook_extra_js_urls:

extra_js_urls(template, database, table, columns, view_name, request, datasette)
--------------------------------------------------------------------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This takes the same arguments as :ref:`extra_template_vars(...) <plugin_hook_extra_template_vars>`

Expand Down Expand Up @@ -288,7 +295,7 @@ Examples: `datasette-cluster-map <https://datasette.io/plugins/datasette-cluster
.. _plugin_hook_extra_body_script:

extra_body_script(template, database, table, columns, view_name, request, datasette)
------------------------------------------------------------------------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Extra JavaScript to be added to a ``<script>`` block at the end of the ``<body>`` element on the page.

Expand Down Expand Up @@ -1430,6 +1437,76 @@ This example logs an error to `Sentry <https://sentry.io/>`__ and then renders a
Example: `datasette-sentry <https://datasette.io/plugins/datasette-sentry>`_

.. _plugin_hook_skip_csrf:

skip_csrf(datasette, scope)
---------------------------

``datasette`` - :ref:`internals_datasette`
You can use this to access plugin configuration options via ``datasette.plugin_config(your_plugin_name)``, or to execute SQL queries.

``scope`` - dictionary
The `ASGI scope <https://asgi.readthedocs.io/en/latest/specs/www.html#http-connection-scope>`__ for the incoming HTTP request.

This hook can be used to skip :ref:`internals_csrf` for a specific incoming request. For example, you might have a custom path at ``/submit-comment`` which is designed to accept comments from anywhere, whether or not the incoming request originated on the site and has an accompanying CSRF token.

This example will disable CSRF protection for that specific URL path:

.. code-block:: python
from datasette import hookimpl
@hookimpl
def skip_csrf(scope):
return scope["path"] == "/submit-comment"
If any of the currently active ``skip_csrf()`` plugin hooks return ``True``, CSRF protection will be skipped for the request.

.. _plugin_hook_get_metadata:

get_metadata(datasette, key, database, table)
---------------------------------------------

``datasette`` - :ref:`internals_datasette`
You can use this to access plugin configuration options via ``datasette.plugin_config(your_plugin_name)``.

``actor`` - dictionary or None
The currently authenticated :ref:`actor <authentication_actor>`.

``database`` - string or None
The name of the database metadata is being asked for.

``table`` - string or None
The name of the table.

``key`` - string or None
The name of the key for which data is being asked for.

This hook is responsible for returning a dictionary corresponding to Datasette :ref:`metadata`. This function is passed the ``database``, ``table`` and ``key`` which were passed to the upstream internal request for metadata. Regardless, it is important to return a global metadata object, where ``"databases": []`` would be a top-level key. The dictionary returned here, will be merged with, and overwritten by, the contents of the physical ``metadata.yaml`` if one is present.

.. warning::
The design of this plugin hook does not currently provide a mechanism for interacting with async code, and may change in the future. See `issue 1384 <https://github.com/simonw/datasette/issues/1384>`__.

.. code-block:: python
@hookimpl
def get_metadata(datasette, key, database, table):
metadata = {
"title": "This will be the Datasette landing page title!",
"description": get_instance_description(datasette),
"databases": [],
}
for db_name, db_data_dict in get_my_database_meta(
datasette, database, table, key
):
metadata["databases"][db_name] = db_data_dict
# whatever we return here will be merged with any other plugins using this hook and
# will be overwritten by a local metadata.yaml if one exists!
return metadata
Example: `datasette-remote-metadata plugin <https://datasette.io/plugins/datasette-remote-metadata>`__

.. _plugin_hook_menu_links:

menu_links(datasette, actor, request)
Expand Down Expand Up @@ -1473,10 +1550,17 @@ Using :ref:`internals_datasette_urls` here ensures that links in the menu will t

Examples: `datasette-search-all <https://datasette.io/plugins/datasette-search-all>`_, `datasette-graphql <https://datasette.io/plugins/datasette-graphql>`_

.. _plugin_actions:

Action hooks
------------

Action hooks can be used to add items to the action menus that appear at the top of different pages within Datasette. Unlike :ref:`menu_links() <plugin_hook_menu_links>`, actions which are displayed on every page, actions should only be relevant to the page the user is currently viewing.

.. _plugin_hook_table_actions:

table_actions(datasette, actor, database, table, request)
---------------------------------------------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

``datasette`` - :ref:`internals_datasette`
You can use this to access plugin configuration options via ``datasette.plugin_config(your_plugin_name)``, or to execute SQL queries.
Expand Down Expand Up @@ -1524,7 +1608,7 @@ Example: `datasette-graphql <https://datasette.io/plugins/datasette-graphql>`_
.. _plugin_hook_view_actions:

view_actions(datasette, actor, database, view, request)
-------------------------------------------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

``datasette`` - :ref:`internals_datasette`
You can use this to access plugin configuration options via ``datasette.plugin_config(your_plugin_name)``, or to execute SQL queries.
Expand All @@ -1546,7 +1630,7 @@ Like :ref:`plugin_hook_table_actions` but for SQL views.
.. _plugin_hook_query_actions:

query_actions(datasette, actor, database, query_name, request, sql, params)
---------------------------------------------------------------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

``datasette`` - :ref:`internals_datasette`
You can use this to access plugin configuration options via ``datasette.plugin_config(your_plugin_name)``, or to execute SQL queries.
Expand Down Expand Up @@ -1603,7 +1687,7 @@ Example: `datasette-create-view <https://datasette.io/plugins/datasette-create-v
.. _plugin_hook_database_actions:

database_actions(datasette, actor, database, request)
-----------------------------------------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

``datasette`` - :ref:`internals_datasette`
You can use this to access plugin configuration options via ``datasette.plugin_config(your_plugin_name)``, or to execute SQL queries.
Expand Down Expand Up @@ -1654,7 +1738,7 @@ Example: `datasette-graphql <https://datasette.io/plugins/datasette-graphql>`_,
.. _plugin_hook_homepage_actions:

homepage_actions(datasette, actor, request)
-------------------------------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

``datasette`` - :ref:`internals_datasette`
You can use this to access plugin configuration options via ``datasette.plugin_config(your_plugin_name)``, or to execute SQL queries.
Expand Down Expand Up @@ -1686,76 +1770,6 @@ This example adds a link an imagined tool for editing the homepage, only for sig
}
]
.. _plugin_hook_skip_csrf:

skip_csrf(datasette, scope)
---------------------------

``datasette`` - :ref:`internals_datasette`
You can use this to access plugin configuration options via ``datasette.plugin_config(your_plugin_name)``, or to execute SQL queries.

``scope`` - dictionary
The `ASGI scope <https://asgi.readthedocs.io/en/latest/specs/www.html#http-connection-scope>`__ for the incoming HTTP request.

This hook can be used to skip :ref:`internals_csrf` for a specific incoming request. For example, you might have a custom path at ``/submit-comment`` which is designed to accept comments from anywhere, whether or not the incoming request originated on the site and has an accompanying CSRF token.

This example will disable CSRF protection for that specific URL path:

.. code-block:: python
from datasette import hookimpl
@hookimpl
def skip_csrf(scope):
return scope["path"] == "/submit-comment"
If any of the currently active ``skip_csrf()`` plugin hooks return ``True``, CSRF protection will be skipped for the request.

.. _plugin_hook_get_metadata:

get_metadata(datasette, key, database, table)
---------------------------------------------

``datasette`` - :ref:`internals_datasette`
You can use this to access plugin configuration options via ``datasette.plugin_config(your_plugin_name)``.

``actor`` - dictionary or None
The currently authenticated :ref:`actor <authentication_actor>`.

``database`` - string or None
The name of the database metadata is being asked for.

``table`` - string or None
The name of the table.

``key`` - string or None
The name of the key for which data is being asked for.

This hook is responsible for returning a dictionary corresponding to Datasette :ref:`metadata`. This function is passed the ``database``, ``table`` and ``key`` which were passed to the upstream internal request for metadata. Regardless, it is important to return a global metadata object, where ``"databases": []`` would be a top-level key. The dictionary returned here, will be merged with, and overwritten by, the contents of the physical ``metadata.yaml`` if one is present.

.. warning::
The design of this plugin hook does not currently provide a mechanism for interacting with async code, and may change in the future. See `issue 1384 <https://github.com/simonw/datasette/issues/1384>`__.

.. code-block:: python
@hookimpl
def get_metadata(datasette, key, database, table):
metadata = {
"title": "This will be the Datasette landing page title!",
"description": get_instance_description(datasette),
"databases": [],
}
for db_name, db_data_dict in get_my_database_meta(
datasette, database, table, key
):
metadata["databases"][db_name] = db_data_dict
# whatever we return here will be merged with any other plugins using this hook and
# will be overwritten by a local metadata.yaml if one exists!
return metadata
Example: `datasette-remote-metadata plugin <https://datasette.io/plugins/datasette-remote-metadata>`__

.. _plugin_hook_slots:

Template slots
Expand Down

0 comments on commit 7339cc5

Please sign in to comment.