sections
582 rows sorted by title
This data as json, CSV (advanced)
page >30 ✖
- changelog 117
- plugin_hooks 46
- authentication 38
- internals 38
- settings 29
- json_api 19
- contributing 17
- cli-reference 14
- metadata 14
- installation 13
- sql_queries 13
- custom_templates 11
- writing_plugins 11
- full_text_search 10
- spatialite 10
- deploying 8
- plugins 8
- publish 8
- configuration 7
- facets 7
- javascript_plugins 7
- testing_plugins 7
- getting_started 6
- pages 6
- performance 5
- binary_data 3
- csv_export 3
- ecosystem 3
- index 2
- events 1
- …
id | page | ref | title ▼ | content | breadcrumbs | references |
---|---|---|---|---|---|---|
changelog:id34 | changelog | id34 | 0.54.1 (2021-02-02) | Fixed a bug where ?_search= and ?_sort= parameters were incorrectly duplicated when the filter form on the table page was re-submitted. ( #1214 ) | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/1214", "label": "#1214"}] |
changelog:id33 | changelog | id33 | 0.55 (2021-02-18) | Support for cross-database SQL queries and built-in support for serving via HTTPS. The new --crossdb command-line option causes Datasette to attach up to ten database files to the same /_memory database connection. This enables cross-database SQL queries, including the ability to use joins and unions to combine data from tables that exist in different database files. See Cross-database queries for details. ( #283 ) --ssl-keyfile and --ssl-certfile options can be used to specify a TLS certificate, allowing Datasette to serve traffic over https:// without needing to run it behind a separate proxy. ( #1221 ) The /:memory: page has been renamed (and redirected) to /_memory for consistency with the new /_internal database introduced in Datasette 0.54. ( #1205 ) Added plugin testing documentation on Using pdb for errors thrown inside Datasette . ( #1207 ) The official Datasette Docker image now uses Python 3.7.10, applying the latest security fix for that Python version. ( #1235 ) | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/283", "label": "#283"}, {"href": "https://github.com/simonw/datasette/issues/1221", "label": "#1221"}, {"href": "https://github.com/simonw/datasette/issues/1205", "label": "#1205"}, {"href": "https://github.com/simonw/datasette/issues/1207", "label": "#1207"}, {"href": "https://hub.docker.com/r/datasetteproject/datasette", "label": "official Datasette Docker image"}, {"href": "https://www.python.org/downloads/release/python-3710/", "label": "the latest security fix"}, {"href": "https://github.com/simonw/datasette/issues/1235", "label": "#1235"}] |
changelog:id32 | changelog | id32 | 0.56 (2021-03-28) | Documentation improvements, bug fixes and support for SpatiaLite 5. The SQL editor can now be resized by dragging a handle. ( #1236 ) Fixed a bug with JSON faceting and the __arraycontains filter caused by tables with spaces in their names. ( #1239 ) Upgraded httpx dependency. ( #1005 ) JSON faceting is now suggested even if a column contains blank strings. ( #1246 ) New datasette.add_memory_database() method. ( #1247 ) The Response.asgi_send() method is now documented. ( #1266 ) The official Datasette Docker image now bundles SpatiaLite version 5. ( #1278 ) Fixed a no such table: pragma_database_list bug when running Datasette against SQLite versions prior to SQLite 3.16.0. ( #1276 ) HTML lists displayed in table cells are now styled correctly. Thanks, Bob Whitelock. ( #1141 , #1252 ) Configuration directory mode now correctly serves immutable databases that are listed in inspect-data.json . Thanks Campbell Allen and Frankie Robertson. ( #1031 , #1229 ) | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/1236", "label": "#1236"}, {"href": "https://github.com/simonw/datasette/issues/1239", "label": "#1239"}, {"href": "https://github.com/simonw/datasette/issues/1005", "label": "#1005"}, {"href": "https://github.com/simonw/datasette/issues/1246", "label": "#1246"}, {"href": "https://github.com/simonw/datasette/issues/1247", "label": "#1247"}, {"href": "https://github.com/simonw/datasette/issues/1266", "label": "#1266"}, {"href": "https://github.com/simonw/datasette/issues/1278", "label": "#1278"}, {"href": "https://github.com/simonw/datasette/issues/1276", "label": "#1276"}, {"href": "https://github.com/simonw/datasette/issues/1141", "label": "#1141"}, {"href": "https://github.com/simonw/datasette/pull/1252", "label": "#1252"}, {"href": "https://github.com/simonw/datasette/pull/1031", "label": "#1031"}, {"href": "https://github.com/simonw/datasette/pull/1229", "label": "#1229"}] |
changelog:id31 | changelog | id31 | 0.56.1 (2021-06-05) | This release fixes a reflected cross-site scripting security hole with the ?_trace=1 feature. You should upgrade to this version, or to Datasette 0.57, as soon as possible. ( #1360 ) | ["Changelog"] | [{"href": "https://owasp.org/www-community/attacks/xss/#reflected-xss-attacks", "label": "reflected cross-site scripting"}, {"href": "https://github.com/simonw/datasette/issues/1360", "label": "#1360"}] |
changelog:id30 | changelog | id30 | 0.57 (2021-06-05) | This release fixes a reflected cross-site scripting security hole with the ?_trace=1 feature. You should upgrade to this version, or to Datasette 0.56.1, as soon as possible. ( #1360 ) In addition to the security fix, this release includes ?_col= and ?_nocol= options for controlling which columns are displayed for a table, ?_facet_size= for increasing the number of facet results returned, re-display of your SQL query should an error occur and numerous bug fixes. | ["Changelog"] | [{"href": "https://owasp.org/www-community/attacks/xss/#reflected-xss-attacks", "label": "reflected cross-site scripting"}, {"href": "https://github.com/simonw/datasette/issues/1360", "label": "#1360"}] |
changelog:id29 | changelog | id29 | 0.57.1 (2021-06-08) | Fixed visual display glitch with global navigation menu. ( #1367 ) No longer truncates the list of table columns displayed on the /database page. ( #1364 ) | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/1367", "label": "#1367"}, {"href": "https://github.com/simonw/datasette/issues/1364", "label": "#1364"}] |
changelog:id28 | changelog | id28 | 0.58 (2021-07-14) | New datasette --uds /tmp/datasette.sock option for binding Datasette to a Unix domain socket, see proxy documentation ( #1388 ) "searchmode": "raw" table metadata option for defaulting a table to executing SQLite full-text search syntax without first escaping it, see Advanced SQLite search queries . ( #1389 ) New plugin hook: get_metadata(datasette, key, database, table) , for returning custom metadata for an instance, database or table. Thanks, Brandon Roberts! ( #1384 ) New plugin hook: skip_csrf(datasette, scope) , for opting out of CSRF protection based on the incoming request. ( #1377 ) The menu_links() , table_actions() and database_actions() plugin hooks all gained a new optional request argument providing access to the current request. ( #1371 ) Major performance improvement for Datasette faceting. ( #1394 ) Improved documentation for Running Datasette behind a proxy to recommend using ProxyPreservehost On with Apache. ( #1387 ) POST requests to endpoints that do not support that HTTP verb now return a 405 error. db.path can now be provided as a pathlib.Path object, useful when writing unit tests for plugins. Thanks, Chris Amico. ( #1365 ) | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/1388", "label": "#1388"}, {"href": "https://github.com/simonw/datasette/issues/1389", "label": "#1389"}, {"href": "https://github.com/simonw/datasette/issues/1384", "label": "#1384"}, {"href": "https://github.com/simonw/datasette/issues/1377", "label": "#1377"}, {"href": "https://github.com/simonw/datasette/issues/1371", "label": "#1371"}, {"href": "https://github.com/simonw/datasette/issues/1394", "label": "#1394"}, {"href": "https://github.com/simonw/datasette/issues/1387", "label": "#1387"}, {"href": "https://github.com/simonw/datasette/issues/1365", "label": "#1365"}] |
changelog:id27 | changelog | id27 | 0.58.1 (2021-07-16) | Fix for an intermittent race condition caused by the refresh_schemas() internal function. ( #1231 ) | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/1231", "label": "#1231"}] |
changelog:id26 | changelog | id26 | 0.59 (2021-10-14) | Columns can now have associated metadata descriptions in metadata.json , see Column descriptions . ( #942 ) New register_commands() plugin hook allows plugins to register additional Datasette CLI commands, e.g. datasette mycommand file.db . ( #1449 ) Adding ?_facet_size=max to a table page now shows the number of unique values in each facet. ( #1423 ) Upgraded dependency httpx 0.20 - the undocumented allow_redirects= parameter to datasette.client is now follow_redirects= , and defaults to False where it previously defaulted to True . ( #1488 ) The --cors option now causes Datasette to return the Access-Control-Allow-Headers: Authorization header, in addition to Access-Control-Allow-Origin: * . ( #1467 ) Code that figures out which named parameters a SQL query takes in order to display form fields for them is no longer confused by strings that contain colon characters. ( #1421 ) Renamed --help-config option to --help-settings . ( #1431 ) datasette.databases property is now a documented API. ( #1443 ) The base.html template now wraps everything other than the <footer> in a <div class="not-footer"> element, to help with advanced CSS customization. ( #1446 ) The render_cell() plugin hook can now return an awaitable function. This means the hook can execute SQL queries. ( #1425 ) register_routes(datasette) plugin hook now accepts an optional datasette argument. ( #1404 ) … | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/942", "label": "#942"}, {"href": "https://github.com/simonw/datasette/issues/1449", "label": "#1449"}, {"href": "https://github.com/simonw/datasette/issues/1423", "label": "#1423"}, {"href": "https://github.com/encode/httpx/releases/tag/0.20.0", "label": "httpx 0.20"}, {"href": "https://github.com/simonw/datasette/issues/1488", "label": "#1488"}, {"href": "https://github.com/simonw/datasette/pull/1467", "label": "#1467"}, {"href": "https://github.com/simonw/datasette/issues/1421", "label": "#1421"}, {"href": "https://github.com/simonw/datasette/issues/1431", "label": "#1431"}, {"href": "https://github.com/simonw/datasette/issues/1443", "label": "#1443"}, {"href": "https://github.com/simonw/datasette/issues/1446", "label": "#1446"}, {"href": "https://github.com/simonw/datasette/issues/1425", "label": "#1425"}, {"href": "https://github.com/simonw/datasette/issues/1404", "label": "#1404"}, {"href": "https://github.com/simonw/datasette/issues/1422", "label": "#1422"}, {"href": "https://github.com/simonw/datasette/issues/1420", "label": "#1420"}, {"href": "https://github.com/willmcgugan/rich", "label": "Rich"}, {"href": "https://github.com/simonw/datasette/issues/1416", "label": "#1416"}, {"href": "https://datasette.io/plugins/datasette-remote-metadata", "label": "datasette-remote-metadata plugin"}, {"href": "https://github.com/simonw/datasette/issues/1405", "label": "#1405"}, {"href": "https://github.com/simonw/datasette/issues/1470", "label": "#1470"}, {"href": "https://github.com/simonw/datasette/issues/1469", "label": "#1469"}] |
changelog:id25 | changelog | id25 | 0.59.1 (2021-10-24) | Fix compatibility with Python 3.10. ( #1482 ) Documentation on how to use Named parameters with integer and floating point values. ( #1496 ) | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/1482", "label": "#1482"}, {"href": "https://github.com/simonw/datasette/issues/1496", "label": "#1496"}] |
changelog:id24 | changelog | id24 | 0.59.2 (2021-11-13) | Column names with a leading underscore now work correctly when used as a facet. ( #1506 ) Applying ?_nocol= to a column no longer removes that column from the filtering interface. ( #1503 ) Official Datasette Docker container now uses Debian Bullseye as the base image. ( #1497 ) Datasette is four years old today! Here's the original release announcement from 2017. | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/1506", "label": "#1506"}, {"href": "https://github.com/simonw/datasette/issues/1503", "label": "#1503"}, {"href": "https://github.com/simonw/datasette/issues/1497", "label": "#1497"}, {"href": "https://simonwillison.net/2017/Nov/13/datasette/", "label": "original release announcement"}] |
changelog:id23 | changelog | id23 | 0.59.3 (2021-11-20) | Fixed numerous bugs when running Datasette behind a proxy with a prefix URL path using the base_url setting. A live demo of this mode is now available at datasette-apache-proxy-demo.datasette.io/prefix/ . ( #1519 , #838 ) ?column__arraycontains= and ?column__arraynotcontains= table parameters now also work against SQL views. ( #448 ) ?_facet_array=column no longer returns incorrect counts if columns contain the same value more than once. | ["Changelog"] | [{"href": "https://datasette-apache-proxy-demo.datasette.io/prefix/", "label": "datasette-apache-proxy-demo.datasette.io/prefix/"}, {"href": "https://github.com/simonw/datasette/issues/1519", "label": "#1519"}, {"href": "https://github.com/simonw/datasette/issues/838", "label": "#838"}, {"href": "https://github.com/simonw/datasette/issues/448", "label": "#448"}] |
changelog:id22 | changelog | id22 | 0.59.4 (2021-11-29) | Fixed bug where columns with a leading underscore could not be removed from the interactive filters list. ( #1527 ) Fixed bug where columns with a leading underscore were not correctly linked to by the "Links from other tables" interface on the row page. ( #1525 ) Upgraded dependencies aiofiles , black and janus . | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/1527", "label": "#1527"}, {"href": "https://github.com/simonw/datasette/issues/1525", "label": "#1525"}] |
changelog:id21 | changelog | id21 | 0.60 (2022-01-13) | ["Changelog"] | [] | |
changelog:id20 | changelog | id20 | 0.60.1 (2022-01-20) | Fixed a bug where installation on Python 3.6 stopped working due to a change to an underlying dependency. This release can now be installed on Python 3.6, but is the last release of Datasette that will support anything less than Python 3.7. ( #1609 ) | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/1609", "label": "#1609"}] |
changelog:id19 | changelog | id19 | 0.60.2 (2022-02-07) | Fixed a bug where Datasette would open the same file twice with two different database names if you ran datasette file.db file.db . ( #1632 ) | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/1632", "label": "#1632"}] |
changelog:id18 | changelog | id18 | 0.61 (2022-03-23) | In preparation for Datasette 1.0, this release includes two potentially backwards-incompatible changes. Hashed URL mode has been moved to a separate plugin, and the way Datasette generates URLs to databases and tables with special characters in their name such as / and . has changed. Datasette also now requires Python 3.7 or higher. URLs within Datasette now use a different encoding scheme for tables or databases that include "special" characters outside of the range of a-zA-Z0-9_- . This scheme is explained here: Tilde encoding . ( #1657 ) Removed hashed URL mode from Datasette. The new datasette-hashed-urls plugin can be used to achieve the same result, see datasette-hashed-urls for details. ( #1661 ) Databases can now have a custom path within the Datasette instance that is independent of the database name, using the db.route property. ( #1668 ) Datasette is now covered by a Code of Conduct . ( #1654 ) Python 3.6 is no longer supported. ( #1577 ) Tests now run against Python 3.11-dev. ( #1621 ) New datasette.ensure_permissions(actor, permissions) internal method for checking multiple permissions at once. ( #1675 ) New datasette.check_visibility(actor, action, resource=None) internal method for checking if a user can see a resource that would otherwise be invisible to unauthenticated users. ( #1678 ) Table and row HTML pages now include a <link rel="alternate" type="application/json+datasette" href="..."> element and return a Link: URL; rel="alternate"; type="applicatio… | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/1657", "label": "#1657"}, {"href": "https://github.com/simonw/datasette/issues/1661", "label": "#1661"}, {"href": "https://github.com/simonw/datasette/issues/1668", "label": "#1668"}, {"href": "https://github.com/simonw/datasette/blob/main/CODE_OF_CONDUCT.md", "label": "Code of Conduct"}, {"href": "https://github.com/simonw/datasette/issues/1654", "label": "#1654"}, {"href": "https://github.com/simonw/datasette/issues/1577", "label": "#1577"}, {"href": "https://github.com/simonw/datasette/issues/1621", "label": "#1621"}, {"href": "https://github.com/simonw/datasette/issues/1675", "label": "#1675"}, {"href": "https://github.com/simonw/datasette/issues/1678", "label": "#1678"}, {"href": "https://github.com/simonw/datasette/issues/1533", "label": "#1533"}, {"href": "https://github.com/simonw/datasette/issues/1612", "label": "#1612"}, {"href": "https://github.com/simonw/datasette/issues/1603", "label": "#1603"}, {"href": "https://github.com/simonw/datasette/issues/1587", "label": "#1587"}, {"href": "https://github.com/simonw/datasette/issues/1601", "label": "#1601"}, {"href": "https://github.com/simonw/datasette/issues/1576", "label": "#1576"}, {"href": "https://github.com/simonw/datasette/issues/957", "label": "#957"}, {"href": "https://github.com/simonw/datasette/issues/1607", "label": "#1607"}, {"href": "https://datasette.io/tutorials", "label": "Datasette Tutorials"}, {"href": "https://github.com/simonw/datasette/pull/1649", "label": "#1649"}, {"href": "https://github.com/simonw/datasette/issues/1545", "label": "#1545"}, {"href": "https://github.com/simonw/datasette/issues/1228", "label": "#1228"}] |
changelog:id17 | changelog | id17 | 0.61.1 (2022-03-23) | Fixed a bug where databases with a different route from their name (as used by the datasette-hashed-urls plugin ) returned errors when executing custom SQL queries. ( #1682 ) | ["Changelog"] | [{"href": "https://datasette.io/plugins/datasette-hashed-urls", "label": "datasette-hashed-urls plugin"}, {"href": "https://github.com/simonw/datasette/issues/1682", "label": "#1682"}] |
changelog:id13 | changelog | id13 | 0.62 (2022-08-14) | Datasette can now run entirely in your browser using WebAssembly. Try out Datasette Lite , take a look at the code or read more about it in Datasette Lite: a server-side Python web application running in a browser . Datasette now has a Discord community for questions and discussions about Datasette and its ecosystem of projects. | ["Changelog"] | [{"href": "https://lite.datasette.io/", "label": "Datasette Lite"}, {"href": "https://github.com/simonw/datasette-lite", "label": "at the code"}, {"href": "https://simonwillison.net/2022/May/4/datasette-lite/", "label": "Datasette Lite: a server-side Python web application running in a browser"}, {"href": "https://datasette.io/discord", "label": "Discord community"}] |
changelog:id11 | changelog | id11 | 0.63 (2022-10-27) | See Datasette 0.63: The annotated release notes for more background on the changes in this release. | ["Changelog"] | [{"href": "https://simonwillison.net/2022/Oct/27/datasette-0-63/", "label": "Datasette 0.63: The annotated release notes"}] |
changelog:id10 | changelog | id10 | 0.63.1 (2022-11-10) | Fixed a bug where Datasette's table filter form would not redirect correctly when run behind a proxy using the base_url setting. ( #1883 ) SQL query is now shown wrapped in a <textarea> if a query exceeds a time limit. ( #1876 ) Fixed an intermittent "Too many open files" error while running the test suite. ( #1843 ) New db.close() internal method. | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/1883", "label": "#1883"}, {"href": "https://github.com/simonw/datasette/issues/1876", "label": "#1876"}, {"href": "https://github.com/simonw/datasette/issues/1843", "label": "#1843"}] |
changelog:id9 | changelog | id9 | 0.63.2 (2022-11-18) | Fixed a bug in datasette publish heroku where deployments failed due to an older version of Python being requested. ( #1905 ) New datasette publish heroku --generate-dir <dir> option for generating a Heroku deployment directory without deploying it. | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/1905", "label": "#1905"}] |
changelog:id8 | changelog | id8 | 0.63.3 (2022-12-17) | Fixed a bug where datasette --root , when running in Docker, would only output the URL to sign in root when the server shut down, not when it started up. ( #1958 ) You no longer need to ensure await datasette.invoke_startup() has been called in order for Datasette to start correctly serving requests - this is now handled automatically the first time the server receives a request. This fixes a bug experienced when Datasette is served directly by an ASGI application server such as Uvicorn or Gunicorn. It also fixes a bug with the datasette-gunicorn plugin. ( #1955 ) | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/1958", "label": "#1958"}, {"href": "https://datasette.io/plugins/datasette-gunicorn", "label": "datasette-gunicorn"}, {"href": "https://github.com/simonw/datasette/issues/1955", "label": "#1955"}] |
changelog:id7 | changelog | id7 | 0.64 (2023-01-09) | Datasette now strongly recommends against allowing arbitrary SQL queries if you are using SpatiaLite . SpatiaLite includes SQL functions that could cause the Datasette server to crash. See SpatiaLite for more details. New default_allow_sql setting, providing an easier way to disable all arbitrary SQL execution by end users: datasette --setting default_allow_sql off . See also Controlling the ability to execute arbitrary SQL . ( #1409 ) Building a location to time zone API with SpatiaLite is a new Datasette tutorial showing how to safely use SpatiaLite to create a location to time zone API. New documentation about how to debug problems loading SQLite extensions . The error message shown when an extension cannot be loaded has also been improved. ( #1979 ) Fixed an accessibility issue: the <select> elements in the table filter form now show an outline when they are currently focused. ( #1771 ) | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/1409", "label": "#1409"}, {"href": "https://datasette.io/tutorials/spatialite", "label": "Building a location to time zone API with SpatiaLite"}, {"href": "https://github.com/simonw/datasette/issues/1979", "label": "#1979"}, {"href": "https://github.com/simonw/datasette/issues/1771", "label": "#1771"}] |
changelog:id6 | changelog | id6 | 0.64.1 (2023-01-11) | Documentation now links to a current source of information for installing Python 3. ( #1987 ) Incorrectly calling the Datasette constructor using Datasette("path/to/data.db") instead of Datasette(["path/to/data.db"]) now returns a useful error message. ( #1985 ) | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/1987", "label": "#1987"}, {"href": "https://github.com/simonw/datasette/issues/1985", "label": "#1985"}] |
changelog:id5 | changelog | id5 | 0.64.2 (2023-03-08) | Fixed a bug with datasette publish cloudrun where deploys all used the same Docker image tag. This was mostly inconsequential as the service is deployed as soon as the image has been pushed to the registry, but could result in the incorrect image being deployed if two different deploys for two separate services ran at exactly the same time. ( #2036 ) | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/2036", "label": "#2036"}] |
changelog:id4 | changelog | id4 | 0.64.4 (2023-09-21) | Fix for a crashing bug caused by viewing the table page for a named in-memory database. ( #2189 ) | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/2189", "label": "#2189"}] |
changelog:id3 | changelog | id3 | 0.64.5 (2023-10-08) | Dropped dependency on click-default-group-wheel , which could cause a dependency conflict. ( #2197 ) | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/2197", "label": "#2197"}] |
changelog:id2 | changelog | id2 | 0.64.6 (2023-12-22) | Fixed a bug where CSV export with expanded labels could fail if a foreign key reference did not correctly resolve. ( #2214 ) | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/2214", "label": "#2214"}] |
changelog:id212 | changelog | id212 | 0.8 (2017-11-13) | V0.8 - added PyPI metadata, ready to ship. Implemented offset/limit pagination for views ( #70 ). Improved pagination. ( #78 ) Limit on max rows returned, controlled by --max_returned_rows option. ( #69 ) If someone executes 'select * from table' against a table with a million rows in it, we could run into problems: just serializing that much data as JSON is likely to lock up the server. Solution: we now have a hard limit on the maximum number of rows that can be returned by a query. If that limit is exceeded, the server will return a "truncated": true field in the JSON. This limit can be optionally controlled by the new --max_returned_rows option. Setting that option to 0 disables the limit entirely. | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/70", "label": "#70"}, {"href": "https://github.com/simonw/datasette/issues/78", "label": "#78"}, {"href": "https://github.com/simonw/datasette/issues/69", "label": "#69"}] |
changelog:id211 | changelog | id211 | 0.9 (2017-11-13) | Added --sql_time_limit_ms and --extra-options . The serve command now accepts --sql_time_limit_ms for customizing the SQL time limit. The publish and package commands now accept --extra-options which can be used to specify additional options to be passed to the datasite serve command when it executes inside the resulting Docker containers. | ["Changelog"] | [] |
changelog:v1-0-a0 | changelog | v1-0-a0 | 1.0a0 (2022-11-29) | This first alpha release of Datasette 1.0 introduces a brand new collection of APIs for writing to the database ( #1850 ), as well as a new API token mechanism baked into Datasette core. Previously, API tokens have only been supported by installing additional plugins. This is very much a preview: expect many more backwards incompatible API changes prior to the full 1.0 release. Feedback enthusiastically welcomed, either through issue comments or via the Datasette Discord community. | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/1850", "label": "#1850"}, {"href": "https://github.com/simonw/datasette/issues/1850", "label": "issue comments"}, {"href": "https://datasette.io/discord", "label": "Datasette Discord"}] |
changelog:v1-0-a1 | changelog | v1-0-a1 | 1.0a1 (2022-12-01) | Write APIs now serve correct CORS headers if Datasette is started in --cors mode. See the full list of CORS headers in the documentation. ( #1922 ) Fixed a bug where the _memory database could be written to even though writes were not persisted. ( #1917 ) The https://latest.datasette.io/ demo instance now includes an ephemeral database which can be used to test Datasette's write APIs, using the new datasette-ephemeral-tables plugin to drop any created tables after five minutes. This database is only available if you sign in as the root user using the link on the homepage. ( #1915 ) Fixed a bug where hitting the write endpoints with a GET request returned a 500 error. It now returns a 405 (method not allowed) error instead. ( #1916 ) The list of endpoints in the API explorer now lists mutable databases first. ( #1918 ) The "ignore": true and "replace": true options for the insert API are now documented . ( #1924 ) | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/1922", "label": "#1922"}, {"href": "https://github.com/simonw/datasette/issues/1917", "label": "#1917"}, {"href": "https://latest.datasette.io/", "label": "https://latest.datasette.io/"}, {"href": "https://datasette.io/plugins/datasette-ephemeral-tables", "label": "datasette-ephemeral-tables"}, {"href": "https://github.com/simonw/datasette/issues/1915", "label": "#1915"}, {"href": "https://github.com/simonw/datasette/issues/1916", "label": "#1916"}, {"href": "https://github.com/simonw/datasette/issues/1918", "label": "#1918"}, {"href": "https://github.com/simonw/datasette/issues/1924", "label": "#1924"}] |
changelog:v1-0-a10 | changelog | v1-0-a10 | 1.0a10 (2024-02-17) | The only changes in this alpha correspond to the way Datasette handles database transactions. ( #2277 ) The database.execute_write_fn() method has a new transaction=True parameter. This defaults to True which means all functions executed using this method are now automatically wrapped in a transaction - previously the functions needed to roll transaction handling on their own, and many did not. Pass transaction=False to execute_write_fn() if you want to manually handle transactions in your function. Several internal Datasette features, including parts of the JSON write API , had been failing to wrap their operations in a transaction. This has been fixed by the new transaction=True default. | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/2277", "label": "#2277"}] |
changelog:v1-0-a11 | changelog | v1-0-a11 | 1.0a11 (2024-02-19) | The "replace": true argument to the /db/table/-/insert API now requires the actor to have the update-row permission. ( #2279 ) Fixed some UI bugs in the interactive permissions debugging tool. ( #2278 ) The column action menu now aligns better with the cog icon, and positions itself taking into account the width of the browser window. ( #2263 ) | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/2279", "label": "#2279"}, {"href": "https://github.com/simonw/datasette/issues/2278", "label": "#2278"}, {"href": "https://github.com/simonw/datasette/issues/2263", "label": "#2263"}] |
changelog:v1-0-a12 | changelog | v1-0-a12 | 1.0a12 (2024-02-29) | New query_actions() plugin hook, similar to table_actions() and database_actions() . Can be used to add a menu of actions to the canned query or arbitrary SQL query page. ( #2283 ) New design for the button that opens the query, table and database actions menu. ( #2281 ) "does not contain" table filter for finding rows that do not contain a string. ( #2287 ) Fixed a bug in the makeColumnActions(columnDetails) JavaScript plugin mechanism where the column action menu was not fully reset in between each interaction. ( #2289 ) | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/2283", "label": "#2283"}, {"href": "https://github.com/simonw/datasette/issues/2281", "label": "#2281"}, {"href": "https://github.com/simonw/datasette/issues/2287", "label": "#2287"}, {"href": "https://github.com/simonw/datasette/issues/2289", "label": "#2289"}] |
changelog:v1-0-a13 | changelog | v1-0-a13 | 1.0a13 (2024-03-12) | Each of the key concepts in Datasette now has an actions menu , which plugins can use to add additional functionality targeting that entity. Plugin hook: view_actions() for actions that can be applied to a SQL view. ( #2297 ) Plugin hook: homepage_actions() for actions that apply to the instance homepage. ( #2298 ) Plugin hook: row_actions() for actions that apply to the row page. ( #2299 ) Action menu items for all of the *_actions() plugin hooks can now return an optional "description" key, which will be displayed in the menu below the action label. ( #2294 ) Plugin hooks documentation page is now organized with additional headings. ( #2300 ) Improved the display of action buttons on pages that also display metadata. ( #2286 ) The header and footer of the page now uses a subtle gradient effect, and options in the navigation menu are better visually defined. ( #2302 ) Table names that start with an underscore now default to hidden. ( #2104 ) pragma_table_list has been added to the allow-list of SQLite pragma functions supported by Datasette. select * from pragma_table_list() is no longer blocked. ( #2104 ) | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/2297", "label": "#2297"}, {"href": "https://github.com/simonw/datasette/issues/2298", "label": "#2298"}, {"href": "https://github.com/simonw/datasette/issues/2299", "label": "#2299"}, {"href": "https://github.com/simonw/datasette/issues/2294", "label": "#2294"}, {"href": "https://github.com/simonw/datasette/issues/2300", "label": "#2300"}, {"href": "https://github.com/simonw/datasette/issues/2286", "label": "#2286"}, {"href": "https://github.com/simonw/datasette/issues/2302", "label": "#2302"}, {"href": "https://github.com/simonw/datasette/issues/2104", "label": "#2104"}, {"href": "https://github.com/simonw/datasette/issues/2104#issuecomment-1982352475", "label": "#2104"}] |
changelog:v1-0-a2 | changelog | v1-0-a2 | 1.0a2 (2022-12-14) | The third Datasette 1.0 alpha release adds upsert support to the JSON API, plus the ability to specify finely grained permissions when creating an API token. See Datasette 1.0a2: Upserts and finely grained permissions for an extended, annotated version of these release notes. New /db/table/-/upsert API, documented here . upsert is an update-or-insert: existing rows will have specified keys updated, but if no row matches the incoming primary key a brand new row will be inserted instead. ( #1878 ) New register_permissions(datasette) plugin hook. Plugins can now register named permissions, which will then be listed in various interfaces that show available permissions. ( #1940 ) The /db/-/create API for creating a table now accepts "ignore": true and "replace": true options when called with the "rows" property that creates a new table based on an example set of rows. This means the API can be called multiple times with different rows, setting rules for what should happen if a primary key collides with an existing row. ( #1927 ) Arbitrary permissions can now be configured at the instance, database and resource (table, SQL view or canned query) level in Datasette's Metadata JSON and YAML files. The new "permissions" key can be used to specify which actors should have which permissions. See Other permissions in datasette.yaml for details. ( #1636 ) The /-/create-token page can now be used to create API tokens which are restricted to just a subset of actions, including against specific databases or resources. See API Tokens for details. ( #1947 ) Likewise, the datasette create-token CLI command can now create tokens with a subset of permis… | ["Changelog"] | [{"href": "https://simonwillison.net/2022/Dec/15/datasette-1a2/", "label": "Datasette 1.0a2: Upserts and finely grained permissions"}, {"href": "https://github.com/simonw/datasette/issues/1878", "label": "#1878"}, {"href": "https://github.com/simonw/datasette/issues/1940", "label": "#1940"}, {"href": "https://github.com/simonw/datasette/issues/1927", "label": "#1927"}, {"href": "https://github.com/simonw/datasette/issues/1636", "label": "#1636"}, {"href": "https://github.com/simonw/datasette/issues/1947", "label": "#1947"}, {"href": "https://github.com/simonw/datasette/issues/1855", "label": "#1855"}, {"href": "https://github.com/simonw/datasette/issues/1951", "label": "#1951"}, {"href": "https://github.com/simonw/datasette/issues/1937", "label": "#1937"}] |
changelog:v1-0-a3 | changelog | v1-0-a3 | 1.0a3 (2023-08-09) | This alpha release previews the updated design for Datasette's default JSON API. ( #782 ) The new default JSON representation for both table pages ( /dbname/table.json ) and arbitrary SQL queries ( /dbname.json?sql=... ) is now shaped like this: { "ok": true, "rows": [ { "id": 3, "name": "Detroit" }, { "id": 2, "name": "Los Angeles" }, { "id": 4, "name": "Memnonia" }, { "id": 1, "name": "San Francisco" } ], "truncated": false } Tables will include an additional "next" key for pagination, which can be passed to ?_next= to fetch the next page of results. The various ?_shape= options continue to work as before - see Different shapes for details. A new ?_extra= mechanism is available for tables, but has not yet been stabilized or documented. Details on that are available in #262 . | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/782", "label": "#782"}, {"href": "https://github.com/simonw/datasette/issues/262", "label": "#262"}] |
changelog:v1-0-a4 | changelog | v1-0-a4 | 1.0a4 (2023-08-21) | This alpha fixes a security issue with the /-/api API explorer. On authenticated Datasette instances (instances protected using plugins such as datasette-auth-passwords ) the API explorer interface could reveal the names of databases and tables within the protected instance. The data stored in those tables was not revealed. For more information and workarounds, read the security advisory . The issue has been present in every previous alpha version of Datasette 1.0: versions 1.0a0, 1.0a1, 1.0a2 and 1.0a3. Also in this alpha: The new datasette plugins --requirements option outputs a list of currently installed plugins in Python requirements.txt format, useful for duplicating that installation elsewhere. ( #2133 ) Writable canned queries can now define a on_success_message_sql field in their configuration, containing a SQL query that should be executed upon successful completion of the write operation in order to generate a message to be shown to the user. ( #2138 ) The automatically generated border color for a database is now shown in more places around the application. ( #2119 ) Every instance of example shell script code in the documentation should now include a working copy button, free from additional syntax. ( #2140 ) | ["Changelog"] | [{"href": "https://datasette.io/plugins/datasette-auth-passwords", "label": "datasette-auth-passwords"}, {"href": "https://github.com/simonw/datasette/security/advisories/GHSA-7ch3-7pp7-7cpq", "label": "the security advisory"}, {"href": "https://github.com/simonw/datasette/issues/2133", "label": "#2133"}, {"href": "https://github.com/simonw/datasette/issues/2138", "label": "#2138"}, {"href": "https://github.com/simonw/datasette/issues/2119", "label": "#2119"}, {"href": "https://github.com/simonw/datasette/issues/2140", "label": "#2140"}] |
changelog:v1-0-a5 | changelog | v1-0-a5 | 1.0a5 (2023-08-29) | When restrictions are applied to API tokens , those restrictions now behave slightly differently: applying the view-table restriction will imply the ability to view-database for the database containing that table, and both view-table and view-database will imply view-instance . Previously you needed to create a token with restrictions that explicitly listed view-instance and view-database and view-table in order to view a table without getting a permission denied error. ( #2102 ) New datasette.yaml (or .json ) configuration file, which can be specified using datasette -c path-to-file . The goal here to consolidate settings, plugin configuration, permissions, canned queries, and other Datasette configuration into a single single file, separate from metadata.yaml . The legacy settings.json config file used for Configuration directory mode has been removed, and datasette.yaml has a "settings" section where the same settings key/value pairs can be included. In the next future alpha release, more configuration such as plugins/permissions/canned queries will be moved to the datasette.yaml file. See #2093 for more details. Thanks, Alex Garcia. The -s/--setting option can now take dotted paths to nested settings. These will then be used to set or over-ride the same options as are present in the new configuration file. ( #2156 ) New --actor '{"id": "json-goes-here"}' option for use with datasette --get to treat the simulated request as being made by a specific actor, see datasette --get . ( #2153 ) The Datasette _internal database has had some changes. It no longer shows up in the datasette.databases list by default, and is now instead available to plugins using the datasette.get_internal_database() . Plugins are invited to use this as a private data… | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/2102", "label": "#2102"}, {"href": "https://github.com/simonw/datasette/issues/2093", "label": "#2093"}, {"href": "https://github.com/simonw/datasette/issues/2156", "label": "#2156"}, {"href": "https://github.com/simonw/datasette/issues/2153", "label": "#2153"}, {"href": "https://github.com/simonw/datasette/issues/2157", "label": "#2157"}] |
changelog:v1-0-a6 | changelog | v1-0-a6 | 1.0a6 (2023-09-07) | New plugin hook: actors_from_ids(datasette, actor_ids) and an internal method to accompany it, await .actors_from_ids(actor_ids) . This mechanism is intended to be used by plugins that may need to display the actor who was responsible for something managed by that plugin: they can now resolve the recorded IDs of actors into the full actor objects. ( #2181 ) DATASETTE_LOAD_PLUGINS environment variable for controlling which plugins are loaded by Datasette. ( #2164 ) Datasette now checks if the user has permission to view a table linked to by a foreign key before turning that foreign key into a clickable link. ( #2178 ) The execute-sql permission now implies that the actor can also view the database and instance. ( #2169 ) Documentation describing a pattern for building plugins that themselves define further hooks for other plugins. ( #1765 ) Datasette is now tested against the Python 3.12 preview. ( #2175 ) | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/2181", "label": "#2181"}, {"href": "https://github.com/simonw/datasette/issues/2164", "label": "#2164"}, {"href": "https://github.com/simonw/datasette/issues/2178", "label": "#2178"}, {"href": "https://github.com/simonw/datasette/issues/2169", "label": "#2169"}, {"href": "https://github.com/simonw/datasette/issues/1765", "label": "#1765"}, {"href": "https://github.com/simonw/datasette/pull/2175", "label": "#2175"}] |
changelog:v1-0-a7 | changelog | v1-0-a7 | 1.0a7 (2023-09-21) | Fix for a crashing bug caused by viewing the table page for a named in-memory database. ( #2189 ) | ["Changelog"] | [{"href": "https://github.com/simonw/datasette/issues/2189", "label": "#2189"}] |
changelog:v1-0-a8 | changelog | v1-0-a8 | 1.0a8 (2024-02-07) | This alpha release continues the migration of Datasette's configuration from metadata.yaml to the new datasette.yaml configuration file, introduces a new system for JavaScript plugins and adds several new plugin hooks. See Datasette 1.0a8: JavaScript plugins, new plugin hooks and plugin configuration in datasette.yaml for an annotated version of these release notes. | ["Changelog"] | [{"href": "https://simonwillison.net/2024/Feb/7/datasette-1a8/", "label": "Datasette 1.0a8: JavaScript plugins, new plugin hooks and plugin configuration in datasette.yaml"}] |
changelog:v1-0-a9 | changelog | v1-0-a9 | 1.0a9 (2024-02-16) | This alpha release adds basic alter table support to the Datasette Write API and fixes a permissions bug relating to the /upsert API endpoint. | ["Changelog"] | [] |
changelog:through-for-joins-through-many-to-many-tables | changelog | through-for-joins-through-many-to-many-tables | ?_through= for joins through many-to-many tables | The new ?_through={json} argument to the Table view allows records to be filtered based on a many-to-many relationship. See Special table arguments for full documentation - here's an example . ( #355 ) This feature was added to help support facet by many-to-many , which isn't quite ready yet but will be coming in the next Datasette release. | ["Changelog", "0.29 (2019-07-07)"] | [{"href": "https://latest.datasette.io/fixtures/roadside_attractions?_through={%22table%22:%22roadside_attraction_characteristics%22,%22column%22:%22characteristic_id%22,%22value%22:%221%22}", "label": "an example"}, {"href": "https://github.com/simonw/datasette/issues/355", "label": "#355"}, {"href": "https://github.com/simonw/datasette/issues/551", "label": "facet by many-to-many"}] |
installation:installation-extensions | installation | installation-extensions | A note about extensions | SQLite supports extensions, such as SpatiaLite for geospatial operations. These can be loaded using the --load-extension argument, like so: datasette --load-extension=/usr/local/lib/mod_spatialite.dylib Some Python installations do not include support for SQLite extensions. If this is the case you will see the following error when you attempt to load an extension: Your Python installation does not have the ability to load SQLite extensions. In some cases you may see the following error message instead: AttributeError: 'sqlite3.Connection' object has no attribute 'enable_load_extension' On macOS the easiest fix for this is to install Datasette using Homebrew: brew install datasette Use which datasette to confirm that datasette will run that version. The output should look something like this: /usr/local/opt/datasette/bin/datasette If you get a different location here such as /Library/Frameworks/Python.framework/Versions/3.10/bin/datasette you can run the following command to cause datasette to execute the Homebrew version instead: alias datasette=$(echo $(brew --prefix datasette)/bin/datasette) You can undo this operation using: unalias datasette If you need to run SQLite with extension support for other Python code, you can do so by install Python itself using Homebrew: brew install python Then executing Python using: /usr/local/opt/python@3/libexec/bin/python A more convenient way to work with this version of Python may be to use it to create a virtual environment: /usr/local/opt/python@3/libexec/bin/python -m venv datasette-venv Then activate it like this: source datasette-venv/bin/activate Now running python and pip will work against a version of … | ["Installation"] | [] |
authentication:createtokenview | authentication | createtokenview | API Tokens | Datasette includes a default mechanism for generating API tokens that can be used to authenticate requests. Authenticated users can create new API tokens using a form on the /-/create-token page. Tokens created in this way can be further restricted to only allow access to specific actions, or to limit those actions to specific databases, tables or queries. Created tokens can then be passed in the Authorization: Bearer $token header of HTTP requests to Datasette. A token created by a user will include that user's "id" in the token payload, so any permissions granted to that user based on their ID can be made available to the token as well. When one of these a token accompanies a request, the actor for that request will have the following shape: { "id": "user_id", "token": "dstok", "token_expires": 1667717426 } The "id" field duplicates the ID of the actor who first created the token. The "token" field identifies that this actor was authenticated using a Datasette signed token ( dstok ). The "token_expires" field, if present, indicates that the token will expire after that integer timestamp. The /-/create-token page cannot be accessed by actors that are authenticated with a "token": "some-value" property. This is to prevent API tokens from being used to create more tokens. Datasette plugins that implement their own form of API token authentication should follow this convention. You can disable the signed token feature entirely using the allow_signed_tokens setting. | ["Authentication and permissions"] | [] |
changelog:asgi | changelog | asgi | ASGI | ASGI is the Asynchronous Server Gateway Interface standard. I've been wanting to convert Datasette into an ASGI application for over a year - Port Datasette to ASGI #272 tracks thirteen months of intermittent development - but with Datasette 0.29 the change is finally released. This also means Datasette now runs on top of Uvicorn and no longer depends on Sanic . I wrote about the significance of this change in Porting Datasette to ASGI, and Turtles all the way down . The most exciting consequence of this change is that Datasette plugins can now take advantage of the ASGI standard. | ["Changelog", "0.29 (2019-07-07)"] | [{"href": "https://asgi.readthedocs.io/", "label": "ASGI"}, {"href": "https://github.com/simonw/datasette/issues/272", "label": "Port Datasette to ASGI #272"}, {"href": "https://www.uvicorn.org/", "label": "Uvicorn"}, {"href": "https://github.com/huge-success/sanic", "label": "Sanic"}, {"href": "https://simonwillison.net/2019/Jun/23/datasette-asgi/", "label": "Porting Datasette to ASGI, and Turtles all the way down"}] |
authentication:authentication-permissions-config | authentication | authentication-permissions-config | Access permissions in | There are two ways to configure permissions using datasette.yaml (or datasette.json ). For simple visibility permissions you can use "allow" blocks in the root, database, table and query sections. For other permissions you can use a "permissions" block, described in the next section . You can limit who is allowed to view different parts of your Datasette instance using "allow" keys in your Configuration . You can control the following: Access to the entire Datasette instance Access to specific databases Access to specific tables and views Access to specific Canned queries If a user cannot access a specific database, they will not be able to access tables, views or queries within that database. If a user cannot access the instance they will not be able to access any of the databases, tables, views or queries. | ["Authentication and permissions"] | [] |
authentication:authentication-permissions-instance | authentication | authentication-permissions-instance | Access to an instance | Here's how to restrict access to your entire Datasette instance to just the "id": "root" user: [[[cog from metadata_doc import config_example config_example(cog, """ title: My private Datasette instance allow: id: root """) ]]] [[[end]]] To deny access to all users, you can use "allow": false : [[[cog config_example(cog, """ title: My entirely inaccessible instance allow: false """) ]]] [[[end]]] One reason to do this is if you are using a Datasette plugin - such as datasette-permissions-sql - to control permissions instead. | ["Authentication and permissions", "Access permissions in "] | [{"href": "https://github.com/simonw/datasette-permissions-sql", "label": "datasette-permissions-sql"}] |
authentication:authentication-permissions-query | authentication | authentication-permissions-query | Access to specific canned queries | Canned queries allow you to configure named SQL queries in your datasette.yaml that can be executed by users. These queries can be set up to both read and write to the database, so controlling who can execute them can be important. To limit access to the add_name canned query in your dogs.db database to just the root user : [[[cog config_example(cog, """ databases: dogs: queries: add_name: sql: INSERT INTO names (name) VALUES (:name) write: true allow: id: - root """) ]]] [[[end]]] | ["Authentication and permissions", "Access permissions in "] | [] |
authentication:authentication-permissions-database | authentication | authentication-permissions-database | Access to specific databases | To limit access to a specific private.db database to just authenticated users, use the "allow" block like this: [[[cog config_example(cog, """ databases: private: allow: id: "*" """) ]]] [[[end]]] | ["Authentication and permissions", "Access permissions in "] | [] |
authentication:authentication-permissions-table | authentication | authentication-permissions-table | Access to specific tables and views | To limit access to the users table in your bakery.db database: [[[cog config_example(cog, """ databases: bakery: tables: users: allow: id: '*' """) ]]] [[[end]]] This works for SQL views as well - you can list their names in the "tables" block above in the same way as regular tables. Restricting access to tables and views in this way will NOT prevent users from querying them using arbitrary SQL queries, like this for example. If you are restricting access to specific tables you should also use the "allow_sql" block to prevent users from bypassing the limit with their own SQL queries - see Controlling the ability to execute arbitrary SQL . | ["Authentication and permissions", "Access permissions in "] | [{"href": "https://latest.datasette.io/fixtures?sql=select+*+from+facetable", "label": "like this"}] |
plugin_hooks:plugin-actions | plugin_hooks | 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 menu_links() , actions which are displayed on every page, actions should only be relevant to the page the user is currently viewing. Each of these hooks should return return a list of {"href": "...", "label": "..."} menu items, with optional "description": "..." keys describing each action in more detail. They can alternatively return an async def awaitable function which, when called, returns a list of those menu items. | ["Plugin hooks"] | [] |
authentication:authentication-actor | authentication | authentication-actor | Actors | Through plugins, Datasette can support both authenticated users (with cookies) and authenticated API agents (via authentication tokens). The word "actor" is used to cover both of these cases. Every request to Datasette has an associated actor value, available in the code as request.actor . This can be None for unauthenticated requests, or a JSON compatible Python dictionary for authenticated users or API agents. The actor dictionary can be any shape - the design of that data structure is left up to the plugins. A useful convention is to include an "id" string, as demonstrated by the "root" actor below. Plugins can use the actor_from_request(datasette, request) hook to implement custom logic for authenticating an actor based on the incoming HTTP request. | ["Authentication and permissions"] | [] |
sql_queries:canned-queries-options | sql_queries | canned-queries-options | Additional canned query options | Additional options can be specified for canned queries in the YAML or JSON configuration. | ["Running SQL queries", "Canned queries"] | [] |
full_text_search:full-text-search-advanced-queries | full_text_search | full-text-search-advanced-queries | Advanced SQLite search queries | SQLite full-text search includes support for a variety of advanced queries , including AND , OR , NOT and NEAR . By default Datasette disables these features to ensure they do not cause errors or confusion for users who are not aware of them. You can disable this escaping and use the advanced queries by adding &_searchmode=raw to the table page query string. If you want to enable these operators by default for a specific table, you can do so by adding "searchmode": "raw" to the metadata configuration for that table, see Configuring full-text search for a table or view . If that option has been specified in the table metadata but you want to over-ride it and return to the default behavior you can append &_searchmode=escaped to the query string. | ["Full-text search"] | [{"href": "https://www.sqlite.org/fts5.html#full_text_query_syntax", "label": "a variety of advanced queries"}] |
installation:installation-advanced | installation | installation-advanced | Advanced installation options | ["Installation"] | [] | |
contributing:contributing-alpha-beta | contributing | contributing-alpha-beta | Alpha and beta releases | Alpha and beta releases are published to preview upcoming features that may not yet be stable - in particular to preview new plugin hooks. You are welcome to try these out, but please be aware that details may change before the final release. Please join discussions on the issue tracker to share your thoughts and experiences with on alpha and beta features that you try out. | ["Contributing"] | [{"href": "https://github.com/simonw/datasette/issues", "label": "discussions on the issue tracker"}] |
changelog:alter-table-support-for-create-insert-upsert-and-update | changelog | alter-table-support-for-create-insert-upsert-and-update | Alter table support for create, insert, upsert and update | The JSON write API can now be used to apply simple alter table schema changes, provided the acting actor has the new alter-table permission. ( #2101 ) The only alter operation supported so far is adding new columns to an existing table. The /db/-/create API now adds new columns during large operations to create a table based on incoming example "rows" , in the case where one of the later rows includes columns that were not present in the earlier batches. This requires the create-table but not the alter-table permission. When /db/-/create is called with rows in a situation where the table may have been already created, an "alter": true key can be included to indicate that any missing columns from the new rows should be added to the table. This requires the alter-table permission. /db/table/-/insert and /db/table/-/upsert and /db/table/row-pks/-/update all now also accept "alter": true , depending on the alter-table permission. Operations that alter a table now fire the new alter-table event . | ["Changelog", "1.0a9 (2024-02-16)"] | [{"href": "https://github.com/simonw/datasette/issues/2101", "label": "#2101"}] |
deploying:apache-proxy-configuration | deploying | apache-proxy-configuration | Apache proxy configuration | For Apache , you can use the ProxyPass directive. First make sure the following lines are uncommented: LoadModule proxy_module lib/httpd/modules/mod_proxy.so LoadModule proxy_http_module lib/httpd/modules/mod_proxy_http.so Then add these directives to proxy traffic: ProxyPass /my-datasette/ http://127.0.0.1:8009/my-datasette/ ProxyPreserveHost On A live demo of Datasette running behind Apache using this proxy setup can be seen at datasette-apache-proxy-demo.datasette.io/prefix/ . The code for that demo can be found in the demos/apache-proxy directory. Using --uds you can use Unix domain sockets similar to the nginx example: ProxyPass /my-datasette/ unix:/tmp/datasette.sock|http://localhost/my-datasette/ The ProxyPreserveHost On directive ensures that the original Host: header from the incoming request is passed through to Datasette. Datasette needs this to correctly assemble links to other pages using the .absolute_url(request, path) method. | ["Deploying Datasette", "Running Datasette behind a proxy"] | [{"href": "https://httpd.apache.org/", "label": "Apache"}, {"href": "https://datasette-apache-proxy-demo.datasette.io/prefix/", "label": "datasette-apache-proxy-demo.datasette.io/prefix/"}, {"href": "https://github.com/simonw/datasette/tree/main/demos/apache-proxy", "label": "demos/apache-proxy"}, {"href": "https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#proxypreservehost", "label": "ProxyPreserveHost On"}] |
changelog:authentication | changelog | authentication | Authentication | Prior to this release the Datasette ecosystem has treated authentication as exclusively the realm of plugins, most notably through datasette-auth-github . 0.44 introduces Authentication and permissions as core Datasette concepts ( #699 ). This enables different plugins to share responsibility for authenticating requests - you might have one plugin that handles user accounts and another one that allows automated access via API keys, for example. You'll need to install plugins if you want full user accounts, but default Datasette can now authenticate a single root user with the new --root command-line option, which outputs a one-time use URL to authenticate as a root actor ( #784 ): datasette fixtures.db --root http://127.0.0.1:8001/-/auth-token?token=5b632f8cd44b868df625f5a6e2185d88eea5b22237fd3cc8773f107cc4fd6477 INFO: Started server process [14973] INFO: Waiting for application startup. INFO: Application startup complete. INFO: Uvicorn running on http://127.0.0.1:8001 (Press CTRL+C to quit) Plugins can implement new ways of authenticating users using the new actor_from_request(datasette, request) hook. | ["Changelog", "0.44 (2020-06-11)"] | [{"href": "https://github.com/simonw/datasette-auth-github", "label": "datasette-auth-github"}, {"href": "https://github.com/simonw/datasette/issues/699", "label": "#699"}, {"href": "https://github.com/simonw/datasette/issues/784", "label": "#784"}] |
authentication:authentication | authentication | authentication | Authentication and permissions | Datasette doesn't require authentication by default. Any visitor to a Datasette instance can explore the full data and execute read-only SQL queries. Datasette's plugin system can be used to add many different styles of authentication, such as user accounts, single sign-on or API keys. | [] | [] |
installation:installation-basic | installation | installation-basic | Basic installation | ["Installation"] | [] | |
changelog:better-plugin-documentation | changelog | better-plugin-documentation | Better plugin documentation | The plugin documentation has been re-arranged into four sections, including a brand new section on testing plugins. ( #687 ) Plugins introduces Datasette's plugin system and describes how to install and configure plugins. Writing plugins describes how to author plugins, from one-off single file plugins to packaged plugins that can be published to PyPI. It also describes how to start a plugin using the new datasette-plugin cookiecutter template. Plugin hooks is a full list of detailed documentation for every Datasette plugin hook. Testing plugins describes how to write tests for Datasette plugins, using pytest and HTTPX . | ["Changelog", "0.45 (2020-07-01)"] | [{"href": "https://github.com/simonw/datasette/issues/687", "label": "#687"}, {"href": "https://github.com/simonw/datasette-plugin", "label": "datasette-plugin"}, {"href": "https://docs.pytest.org/", "label": "pytest"}, {"href": "https://www.python-httpx.org/", "label": "HTTPX"}] |
binary_data:binary | binary_data | binary | Binary data | SQLite tables can contain binary data in BLOB columns. Datasette includes special handling for these binary values. The Datasette interface detects binary values and provides a link to download their content, for example on https://latest.datasette.io/fixtures/binary_data Binary data is represented in .json exports using Base64 encoding. https://latest.datasette.io/fixtures/binary_data.json?_shape=array [ { "rowid": 1, "data": { "$base64": true, "encoded": "FRwCx60F/g==" } }, { "rowid": 2, "data": { "$base64": true, "encoded": "FRwDx60F/g==" } }, { "rowid": 3, "data": null } ] | [] | [{"href": "https://latest.datasette.io/fixtures/binary_data", "label": "https://latest.datasette.io/fixtures/binary_data"}, {"href": "https://latest.datasette.io/fixtures/binary_data.json?_shape=array", "label": "https://latest.datasette.io/fixtures/binary_data.json?_shape=array"}] |
changelog:binary-data | changelog | binary-data | Binary data | SQLite tables can contain binary data in BLOB columns. Datasette now provides links for users to download this data directly from Datasette, and uses those links to make binary data available from CSV exports. See Binary data for more details. ( #1036 and #1034 ). | ["Changelog", "0.51 (2020-10-31)"] | [{"href": "https://github.com/simonw/datasette/issues/1036", "label": "#1036"}, {"href": "https://github.com/simonw/datasette/issues/1034", "label": "#1034"}] |
binary_data:binary-plugins | binary_data | binary-plugins | Binary plugins | Several Datasette plugins are available that change the way Datasette treats binary data. datasette-render-binary modifies Datasette's default interface to show an automatic guess at what type of binary data is being stored, along with a visual representation of the binary value that displays ASCII strings directly in the interface. datasette-render-images detects common image formats and renders them as images directly in the Datasette interface. datasette-media allows Datasette interfaces to be configured to serve binary files from configured SQL queries, and includes the ability to resize images directly before serving them. | ["Binary data"] | [{"href": "https://github.com/simonw/datasette-render-binary", "label": "datasette-render-binary"}, {"href": "https://github.com/simonw/datasette-render-images", "label": "datasette-render-images"}, {"href": "https://github.com/simonw/datasette-media", "label": "datasette-media"}] |
changelog:bug-fixes | changelog | bug-fixes | Bug fixes | Don't show the facet option in the cog menu if faceting is not allowed. ( #1683 ) ?_sort and ?_sort_desc now work if the column that is being sorted has been excluded from the query using ?_col= or ?_nocol= . ( #1773 ) Fixed bug where ?_sort_desc was duplicated in the URL every time the Apply button was clicked. ( #1738 ) | ["Changelog", "0.62 (2022-08-14)"] | [{"href": "https://github.com/simonw/datasette/issues/1683", "label": "#1683"}, {"href": "https://github.com/simonw/datasette/issues/1773", "label": "#1773"}, {"href": "https://github.com/simonw/datasette/issues/1738", "label": "#1738"}] |
changelog:bug-fixes-and-other-improvements | changelog | bug-fixes-and-other-improvements | Bug fixes and other improvements | Custom pages now work correctly when combined with the base_url setting. ( #1238 ) Fixed intermittent error displaying the index page when the user did not have permission to access one of the tables. Thanks, Guy Freeman. ( #1305 ) Columns with the name "Link" are no longer incorrectly displayed in bold. ( #1308 ) Fixed error caused by tables with a single quote in their names. ( #1257 ) Updated dependencies: pytest-asyncio , Black , jinja2 , aiofiles , click , and itsdangerous . The official Datasette Docker image now supports apt-get install . ( #1320 ) The Heroku runtime used by datasette publish heroku is now python-3.8.10 . | ["Changelog", "0.57 (2021-06-05)"] | [{"href": "https://github.com/simonw/datasette/issues/1238", "label": "#1238"}, {"href": "https://github.com/simonw/datasette/issues/1305", "label": "#1305"}, {"href": "https://github.com/simonw/datasette/issues/1308", "label": "#1308"}, {"href": "https://github.com/simonw/datasette/issues/1257", "label": "#1257"}, {"href": "https://github.com/simonw/datasette/issues/1320", "label": "#1320"}] |
writing_plugins:writing-plugins-building-urls | writing_plugins | writing-plugins-building-urls | Building URLs within plugins | Plugins that define their own custom user interface elements may need to link to other pages within Datasette. This can be a bit tricky if the Datasette instance is using the base_url configuration setting to run behind a proxy, since that can cause Datasette's URLs to include an additional prefix. The datasette.urls object provides internal methods for correctly generating URLs to different pages within Datasette, taking any base_url configuration into account. This object is exposed in templates as the urls variable, which can be used like this: Back to the <a href="{{ urls.instance() }}">Homepage</a> See datasette.urls for full details on this object. | ["Writing plugins"] | [] |
authentication:id1 | authentication | id1 | Built-in permissions | This section lists all of the permission checks that are carried out by Datasette core, along with the resource if it was passed. | ["Authentication and permissions"] | [] |
cli-reference:id1 | cli-reference | id1 | CLI reference | The datasette CLI tool provides a number of commands. Running datasette without specifying a command runs the default command, datasette serve . See datasette serve for the full list of options for that command. [[[cog from datasette import cli from click.testing import CliRunner import textwrap def help(args): title = "datasette " + " ".join(args) cog.out("\n::\n\n") result = CliRunner().invoke(cli.cli, args) output = result.output.replace("Usage: cli ", "Usage: datasette ") cog.out(textwrap.indent(output, ' ')) cog.out("\n\n") ]]] [[[end]]] | [] | [] |
changelog:csrf-protection | changelog | csrf-protection | CSRF protection | Since writable canned queries are built using POST forms, Datasette now ships with CSRF protection ( #798 ). This applies automatically to any POST request, which means plugins need to include a csrftoken in any POST forms that they render. They can do that like so: <input type="hidden" name="csrftoken" value="{{ csrftoken() }}"> | ["Changelog", "0.44 (2020-06-11)"] | [{"href": "https://github.com/simonw/datasette/issues/798", "label": "#798"}] |
internals:internals-csrf | internals | internals-csrf | CSRF protection | Datasette uses asgi-csrf to guard against CSRF attacks on form POST submissions. Users receive a ds_csrftoken cookie which is compared against the csrftoken form field (or x-csrftoken HTTP header) for every incoming request. If your plugin implements a <form method="POST"> anywhere you will need to include that token. You can do so with the following template snippet: <input type="hidden" name="csrftoken" value="{{ csrftoken() }}"> If you are rendering templates using the await .render_template(template, context=None, request=None) method the csrftoken() helper will only work if you provide the request= argument to that method. If you forget to do this you will see the following error: form-urlencoded POST field did not match cookie You can selectively disable CSRF protection using the skip_csrf(datasette, scope) hook. | ["Internals for plugins"] | [{"href": "https://github.com/simonw/asgi-csrf", "label": "asgi-csrf"}] |
custom_templates:css-classes-on-the-body | custom_templates | css-classes-on-the-body | CSS classes on the <body> | Every default template includes CSS classes in the body designed to support custom styling. The index template (the top level page at / ) gets this: <body class="index"> The database template ( /dbname ) gets this: <body class="db db-dbname"> The custom SQL template ( /dbname?sql=... ) gets this: <body class="query db-dbname"> A canned query template ( /dbname/queryname ) gets this: <body class="query db-dbname query-queryname"> The table template ( /dbname/tablename ) gets: <body class="table db-dbname table-tablename"> The row template ( /dbname/tablename/rowid ) gets: <body class="row db-dbname table-tablename"> The db-x and table-x classes use the database or table names themselves if they are valid CSS identifiers. If they aren't, we strip any invalid characters out and append a 6 character md5 digest of the original name, in order to ensure that multiple tables which resolve to the same stripped character version still have different CSS classes. Some examples: "simple" => "simple" "MixedCase" => "MixedCase" "-no-leading-hyphens" => "no-leading-hyphens-65bea6" "_no-leading-underscores" => "no-leading-underscores-b921bc" "no spaces" => "no-spaces-7088d7" "-" => "336d5e" "no $ characters" => "no--characters-59e024" <td> and <th> elements also get custom CSS classes reflecting the database column they are representing, for example: <table> <thead> <tr> <th class="col-id" scope="col">id</th> <th class="col-name" scope="col">name</th> </tr> </thead> <tbody> <tr> <td class="col-id"><a href="...">1</a></td> <td class="col-name">SMITH</td> </tr> </tbody> </table> | ["Custom pages and templates"] | [] |
changelog:csv-export | changelog | csv-export | CSV export | Any Datasette table, view or custom SQL query can now be exported as CSV. Check out the CSV export documentation for more details, or try the feature out on https://fivethirtyeight.datasettes.com/fivethirtyeight/bechdel%2Fmovies If your table has more than max_returned_rows (default 1,000) Datasette provides the option to stream all rows . This option takes advantage of async Python and Datasette's efficient pagination to iterate through the entire matching result set and stream it back as a downloadable CSV file. | ["Changelog", "0.23 (2018-06-18)"] | [{"href": "https://fivethirtyeight.datasettes.com/fivethirtyeight/bechdel%2Fmovies", "label": "https://fivethirtyeight.datasettes.com/fivethirtyeight/bechdel%2Fmovies"}] |
csv_export:id1 | csv_export | id1 | CSV export | Any Datasette table, view or custom SQL query can be exported as CSV. To obtain the CSV representation of the table you are looking, click the "this data as CSV" link. You can also use the advanced export form for more control over the resulting file, which looks like this and has the following options: download file - instead of displaying CSV in your browser, this forces your browser to download the CSV to your downloads directory. expand labels - if your table has any foreign key references this option will cause the CSV to gain additional COLUMN_NAME_label columns with a label for each foreign key derived from the linked table. In this example the city_id column is accompanied by a city_id_label column. stream all rows - by default CSV files only contain the first max_returned_rows records. This option will cause Datasette to loop through every matching record and return them as a single CSV file. You can try that out on https://latest.datasette.io/fixtures/facetable?_size=4 | [] | [{"href": "https://latest.datasette.io/fixtures/facetable.csv?_labels=on&_size=max", "label": "In this example"}, {"href": "https://latest.datasette.io/fixtures/facetable?_size=4", "label": "https://latest.datasette.io/fixtures/facetable?_size=4"}] |
sql_queries:id1 | sql_queries | id1 | 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: [[[cog from metadata_doc import config_example, config_example config_example(cog, { "databases": { "sf-trees": { "queries": { "just_species": { "sql": "select qSpecies from Street_Tree_List" } } } } }) ]]] [[[end]]] Then run Datasette like this: datasette sf-trees.db -m metadata.json Each canned query will be listed on the database index page, and will also get its own URL at: /database-name/canned-query-name For the above example, that URL would be: /sf-trees/just_species You can optionally include "title" and "description" keys to show a 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). | ["Running SQL queries"] | [] |
configuration:configuration-reference-canned-queries | configuration | configuration-reference-canned-queries | Canned queries configuration | Canned queries are named SQL queries that appear in the Datasette interface. They can be configured in datasette.yaml using the queries key at the database level: [[[cog from metadata_doc import config_example, config_example config_example(cog, { "databases": { "sf-trees": { "queries": { "just_species": { "sql": "select qSpecies from Street_Tree_List" } } } } }) ]]] [[[end]]] See the canned queries documentation for more, including how to configure writable canned queries . | ["Configuration", null] | [] |
sql_queries:canned-queries-named-parameters | sql_queries | canned-queries-named-parameters | Canned query 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 custom JSON APIs based on a carefully designed SQL statement. Here's an example of a canned query with a named parameter: 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; In the canned query configuration looks like this: [[[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 """) ]]] [[[end]]] Note that we are using SQLite string concatenation here - the || operator - to add wildcard % characters to the string provided by the user. You can try this canned query out here: https://latest.datasette.io/fixtures/neighborhood_search?text=town In this example the :text named parameter is automatically extracted from the query using a regular expression. You can alternatively provide an explicit list of named parameters using the "params" key, like this: [[[cog config_example(cog, """ 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 … | ["Running SQL queries", "Canned queries"] | [{"href": "https://latest.datasette.io/fixtures/neighborhood_search?text=town", "label": "https://latest.datasette.io/fixtures/neighborhood_search?text=town"}] |
changelog:id1 | changelog | id1 | Changelog | [] | [] | |
authentication:permissions-plugins | authentication | permissions-plugins | Checking permissions in plugins | Datasette plugins can check if an actor has permission to perform an action using the datasette.permission_allowed(...) method. Datasette core performs a number of permission checks, documented below . Plugins can implement the permission_allowed(datasette, actor, action, resource) plugin hook to participate in decisions about whether an actor should be able to perform a specified action. | ["Authentication and permissions"] | [] |
contributing:contributing-formatting | contributing | contributing-formatting | Code formatting | Datasette uses opinionated code formatters: Black for Python and Prettier for JavaScript. These formatters are enforced by Datasette's continuous integration: if a commit includes Python or JavaScript code that does not match the style enforced by those tools, the tests will fail. When developing locally, you can verify and correct the formatting of your code using these tools. | ["Contributing"] | [{"href": "https://github.com/psf/black", "label": "Black"}, {"href": "https://prettier.io/", "label": "Prettier"}] |
changelog:code-formatting-with-black-and-prettier | changelog | code-formatting-with-black-and-prettier | Code formatting with Black and Prettier | Datasette adopted Black for opinionated Python code formatting in June 2019. Datasette now also embraces Prettier for JavaScript formatting, which like Black is enforced by tests in continuous integration. Instructions for using these two tools can be found in the new section on Code formatting in the contributors documentation. ( #1167 ) | ["Changelog", "0.54 (2021-01-25)"] | [{"href": "https://github.com/psf/black", "label": "Black"}, {"href": "https://prettier.io/", "label": "Prettier"}, {"href": "https://github.com/simonw/datasette/issues/1167", "label": "#1167"}] |
metadata:metadata-column-descriptions | metadata | metadata-column-descriptions | Column descriptions | You can include descriptions for your columns by adding a "columns": {"name-of-column": "description-of-column"} block to your table metadata: [[[cog metadata_example(cog, { "databases": { "database1": { "tables": { "example_table": { "columns": { "column1": "Description of column 1", "column2": "Description of column 2" } } } } } }) ]]] [[[end]]] These will be displayed at the top of the table page, and will also show in the cog menu for each column. You can see an example of how these look at latest.datasette.io/fixtures/roadside_attractions . | ["Metadata"] | [{"href": "https://latest.datasette.io/fixtures/roadside_attractions", "label": "latest.datasette.io/fixtures/roadside_attractions"}] |
json_api:column-filter-arguments | json_api | column-filter-arguments | Column filter arguments | You can filter the data returned by the table based on column values using a query string argument. ?column__exact=value or ?_column=value Returns rows where the specified column exactly matches the value. ?column__not=value Returns rows where the column does not match the value. ?column__contains=value Rows where the string column contains the specified value ( column like "%value%" in SQL). ?column__notcontains=value Rows where the string column does not contain the specified value ( column not like "%value%" in SQL). ?column__endswith=value Rows where the string column ends with the specified value ( column like "%value" in SQL). ?column__startswith=value Rows where the string column starts with the specified value ( column like "value%" in SQL). ?column__gt=value Rows which are greater than the specified value. ?column__gte=value Rows which… | ["JSON API", "Table arguments"] | [] |
changelog:configuration | changelog | configuration | Configuration | Plugin configuration now lives in the datasette.yaml configuration file , passed to Datasette using the -c/--config option. Thanks, Alex Garcia. ( #2093 ) datasette -c datasette.yaml Where datasette.yaml contains configuration that looks like this: plugins: datasette-cluster-map: latitude_column: xlat longitude_column: xlon Previously plugins were configured in metadata.yaml , which was confusing as plugin settings were unrelated to database and table metadata. The -s/--setting option can now be used to set plugin configuration as well. See Configuration via the command-line for details. ( #2252 ) The above YAML configuration example using -s/--setting looks like this: datasette mydatabase.db \ -s plugins.datasette-cluster-map.latitude_column xlat \ -s plugins.datasette-cluster-map.longitude_column xlon The new /-/config page shows the current instance configuration, after redacting keys that could contain sensitive data such as API keys or passwords. ( #2254 ) Existing Datasette installations may already have configuration set in metadata.yaml that should be migrated to datasette.yaml . To avoid breaking these installations, Datasette will silently treat table configuration, plugin configuration and allow blocks in metadata as if they had been specified in configuration instead. ( #2247 ) ( #2248 ) ( #2249 ) Note that the datasette publish command has not yet been updated to accept a datasette.yaml configuration file. This will be addressed in #2195 but for the moment you can include those settings in metadata.yaml instead. | ["Changelog", "1.0a8 (2024-02-07)"] | [{"href": "https://github.com/simonw/datasette/issues/2093", "label": "#2093"}, {"href": "https://github.com/simonw/datasette/issues/2252", "label": "#2252"}, {"href": "https://github.com/simonw/datasette/issues/2254", "label": "#2254"}, {"href": "https://github.com/simonw/datasette/issues/2247", "label": "#2247"}, {"href": "https://github.com/simonw/datasette/issues/2248", "label": "#2248"}, {"href": "https://github.com/simonw/datasette/issues/2249", "label": "#2249"}, {"href": "https://github.com/simonw/datasette/issues/2195", "label": "#2195"}] |
configuration:id1 | configuration | id1 | Configuration | Datasette offers several ways to configure your Datasette instances: server settings, plugin configuration, authentication, and more. Most configuration can be handled using a datasette.yaml configuration file, passed to datasette using the -c/--config flag: datasette mydatabase.db --config datasette.yaml This file can also use JSON, as datasette.json . YAML is recommended over JSON due to its support for comments and multi-line strings. | [] | [] |
settings:config-dir | settings | config-dir | Configuration directory mode | Normally you configure Datasette using command-line options. For a Datasette instance with custom templates, custom plugins, a static directory and several databases this can get quite verbose: datasette one.db two.db \ --metadata=metadata.json \ --template-dir=templates/ \ --plugins-dir=plugins \ --static css:css As an alternative to this, you can run Datasette in configuration directory mode. Create a directory with the following structure: # In a directory called my-app: my-app/one.db my-app/two.db my-app/datasette.yaml my-app/metadata.json my-app/templates/index.html my-app/plugins/my_plugin.py my-app/static/my.css Now start Datasette by providing the path to that directory: datasette my-app/ Datasette will detect the files in that directory and automatically configure itself using them. It will serve all *.db files that it finds, will load metadata.json if it exists, and will load the templates , plugins and static folders if they are present. The files that can be included in this directory are as follows. All are optional. *.db (or *.sqlite3 or *.sqlite ) - SQLite database files that will be served by Datasette datasette.yaml - Configuration for the Datasette instance metadata.json - Metadata for those databases - metadata.yaml or metadata.yml can be used as well inspect-data.json - the result of running datasette inspect *.db --inspect-file=inspect-data.json from the configuration directory - any database files listed here will be treated as immutable, so they should not be changed while Datasette is running templates/ - a directory containing Custom templates … | ["Settings"] | [] |
configuration:configuration-cli | configuration | configuration-cli | Configuration via the command-line | The recommended way to configure Datasette is using a datasette.yaml file passed to -c/--config . You can also pass individual settings to Datasette using the -s/--setting option, which can be used multiple times: datasette mydatabase.db \ --setting settings.default_page_size 50 \ --setting settings.sql_time_limit_ms 3500 This option takes dotted-notation for the first argument and a value for the second argument. This means you can use it to set any configuration value that would be valid in a datasette.yaml file. It also works for plugin configuration, for example for datasette-cluster-map : datasette mydatabase.db \ --setting plugins.datasette-cluster-map.latitude_column xlat \ --setting plugins.datasette-cluster-map.longitude_column xlon If the value you provide is a valid JSON object or list it will be treated as nested data, allowing you to configure plugins that accept lists such as datasette-proxy-url : datasette mydatabase.db \ -s plugins.datasette-proxy-url.paths '[{"path": "/proxy", "backend": "http://example.com/"}]' This is equivalent to a datasette.yaml file containing the following: [[[cog from metadata_doc import config_example import textwrap config_example(cog, textwrap.dedent( """ plugins: datasette-proxy-url: paths: - path: /proxy backend: http://example.com/ """).strip() ) ]]] [[[end]]] | ["Configuration"] | [{"href": "https://datasette.io/plugins/datasette-cluster-map", "label": "datasette-cluster-map"}, {"href": "https://datasette.io/plugins/datasette-proxy-url", "label": "datasette-proxy-url"}] |
full_text_search:configuring-fts-by-hand | full_text_search | configuring-fts-by-hand | Configuring FTS by hand | We recommend using sqlite-utils , but if you want to hand-roll a SQLite full-text search table you can do so using the following SQL. To enable full-text search for a table called items that works against the name and description columns, you would run this SQL to create a new items_fts FTS virtual table: CREATE VIRTUAL TABLE "items_fts" USING FTS4 ( name, description, content="items" ); This creates a set of tables to power full-text search against items . The new items_fts table will be detected by Datasette as the fts_table for the items table. Creating the table is not enough: you also need to populate it with a copy of the data that you wish to make searchable. You can do that using the following SQL: INSERT INTO "items_fts" (rowid, name, description) SELECT rowid, name, description FROM items; If your table has columns that are foreign key references to other tables you can include that data in your full-text search index using a join. Imagine the items table has a foreign key column called category_id which refers to a categories table - you could create a full-text search table like this: CREATE VIRTUAL TABLE "items_fts" USING FTS4 ( name, description, category_name, content="items" ); And then populate it like this: INSERT INTO "items_fts" (rowid, name, description, category_name) SELECT items.rowid, items.name, items.description, categories.name FROM items JOIN categories ON items.category_id=categories.id; You can use this technique to populate the full-text search index from any combination of tables and joins that makes sense for your project. | ["Full-text search", "Enabling full-text search for a SQLite table"] | [{"href": "https://sqlite-utils.datasette.io/", "label": "sqlite-utils"}] |
full_text_search:configuring-fts-using-csvs-to-sqlite | full_text_search | configuring-fts-using-csvs-to-sqlite | Configuring FTS using csvs-to-sqlite | If your data starts out in CSV files, you can use Datasette's companion tool csvs-to-sqlite to convert that file into a SQLite database and enable full-text search on specific columns. For a file called items.csv where you want full-text search to operate against the name and description columns you would run the following: csvs-to-sqlite items.csv items.db -f name -f description | ["Full-text search", "Enabling full-text search for a SQLite table"] | [{"href": "https://github.com/simonw/csvs-to-sqlite", "label": "csvs-to-sqlite"}] |
full_text_search:configuring-fts-using-sqlite-utils | full_text_search | configuring-fts-using-sqlite-utils | Configuring FTS using sqlite-utils | sqlite-utils is a CLI utility and Python library for manipulating SQLite databases. You can use it from Python code to configure FTS search, or you can achieve the same goal using the accompanying command-line tool . Here's how to use sqlite-utils to enable full-text search for an items table across the name and description columns: sqlite-utils enable-fts mydatabase.db items name description | ["Full-text search", "Enabling full-text search for a SQLite table"] | [{"href": "https://sqlite-utils.datasette.io/", "label": "sqlite-utils"}, {"href": "https://sqlite-utils.datasette.io/en/latest/python-api.html#enabling-full-text-search", "label": "it from Python code"}, {"href": "https://sqlite-utils.datasette.io/en/latest/cli.html#configuring-full-text-search", "label": "using the accompanying command-line tool"}] |
full_text_search:full-text-search-table-or-view | full_text_search | full-text-search-table-or-view | Configuring full-text search for a table or view | If a table has a corresponding FTS table set up using the content= argument to CREATE VIRTUAL TABLE shown below, Datasette will detect it automatically and add a search interface to the table page for that table. You can also manually configure which table should be used for full-text search using query string parameters or Metadata . You can set the associated FTS table for a specific table and you can also set one for a view - if you do that, the page for that SQL view will offer a search option. Use ?_fts_table=x to over-ride the FTS table for a specific page. If the primary key was something other than rowid you can use ?_fts_pk=col to set that as well. This is particularly useful for views, for example: https://latest.datasette.io/fixtures/searchable_view?_fts_table=searchable_fts&_fts_pk=pk The fts_table metadata property can be used to specify an associated FTS table. If the primary key column in your table which was used to populate the FTS table is something other than rowid , you can specify the column to use with the fts_pk property. The "searchmode": "raw" property can be used to default the table to accepting SQLite advanced search operators, as described in Advanced SQLite search queries . Here is an example which enables full-text search (with SQLite advanced search operators) for a display_ads view which is defined against the ads table and hence needs to run FTS against the ads_fts table, using the id as the primary key: [[[cog from metadata_doc import metadata_example metadata_example(cog, { "databases": { "russian-ads": { "tables": { "display_ads": { "fts_table": "ads_fts", "fts_pk": "id", "searchmode": "raw" } } } } }) ]]] [[[end]]] | ["Full-text search"] | [{"href": "https://latest.datasette.io/fixtures/searchable_view?_fts_table=searchable_fts&_fts_pk=pk", "label": "https://latest.datasette.io/fixtures/searchable_view?_fts_table=searchable_fts&_fts_pk=pk"}] |
settings:setting-secret | settings | setting-secret | Configuring the secret | Datasette uses a secret string to sign secure values such as cookies. If you do not provide a secret, Datasette will create one when it starts up. This secret will reset every time the Datasette server restarts though, so things like authentication cookies and API tokens will not stay valid between restarts. You can pass a secret to Datasette in two ways: with the --secret command-line option or by setting a DATASETTE_SECRET environment variable. datasette mydb.db --secret=SECRET_VALUE_HERE Or: export DATASETTE_SECRET=SECRET_VALUE_HERE datasette mydb.db One way to generate a secure random secret is to use Python like this: python3 -c 'import secrets; print(secrets.token_hex(32))' cdb19e94283a20f9d42cca50c5a4871c0aa07392db308755d60a1a5b9bb0fa52 Plugin authors make use of this signing mechanism in their plugins using .sign(value, namespace="default") and .unsign(value, namespace="default") . | ["Settings"] | [] |
index:contents | index | contents | Contents | Getting started Play with a live demo Follow a tutorial Datasette in your browser with Datasette Lite Try Datasette without installing anything using Glitch Using Datasette on your own computer Installation Basic installation Datasette Desktop for Mac Using Homebrew Using pip Advanced installation options Using pipx Using Docker A note about extensions Configuration Configuration via the command-line datasette.yaml reference Settings Plugin configuration Permissions configuration Canned queries configuration Custom CSS and JavaScript The Datasette Ecosystem sqlite-utils Dogsheep CLI reference datasette --help datasette serve datasette --get datasette serve --help-settings datasette plugins datasette install datasette uninstall datasette publish datasette publish cloudrun datasette publish heroku datasette package datasette inspect datasette create-token Pages and API endpoints Top-level index Database Hidden tables Table Row Publishing data datasette publish Publishing to Google Cloud Run Publishing to Heroku Publishing to Vercel Publishing to Fly Custom metadata and plugins datasette package Deploying Datasette Deployment fundamentals Running Datasette using systemd Running Datasette using OpenRC Deploying using buildpacks Running Datasette behind a proxy Nginx proxy configuration Apache proxy configuration JSON API Default representation Different shapes Pagination Special JSON arguments Table arguments Column filter arguments Special table arguments Expanding foreign key references Discovering the JSON for a page Enabling CORS The JSON write API Inserting rows Upserting rows Updating a row Deleting a row Creating a table Creating a table from example data Dropping tables Running SQL queries Named parameters Views Canned queries Canned query parameters Additional canned query options Writable canned queries Magic parameters JSON API for writable canned queries Pagination Cross-database queries Authentication and permissions Actors Using the "root" actor Permissions How permissions are resolved Defining permiss… | ["Datasette"] | [] |
contributing:contributing-continuous-deployment | contributing | contributing-continuous-deployment | Continuously deployed demo instances | The demo instance at latest.datasette.io is re-deployed automatically to Google Cloud Run for every push to main that passes the test suite. This is implemented by the GitHub Actions workflow at .github/workflows/deploy-latest.yml . Specific branches can also be set to automatically deploy by adding them to the on: push: branches block at the top of the workflow YAML file. Branches configured in this way will be deployed to a new Cloud Run service whether or not their tests pass. The Cloud Run URL for a branch demo can be found in the GitHub Actions logs. | ["Contributing"] | [{"href": "https://latest.datasette.io/", "label": "latest.datasette.io"}, {"href": "https://github.com/simonw/datasette/blob/main/.github/workflows/deploy-latest.yml", "label": ".github/workflows/deploy-latest.yml"}] |
contributing:id1 | contributing | id1 | Contributing | Datasette is an open source project. We welcome contributions! This document describes how to contribute to Datasette core. You can also contribute to the wider Datasette ecosystem by creating new Plugins . | [] | [] |
Advanced export
JSON shape: default, array, newline-delimited, object
CREATE TABLE [sections] ( [id] TEXT PRIMARY KEY, [page] TEXT, [ref] TEXT, [title] TEXT, [content] TEXT, [breadcrumbs] TEXT, [references] TEXT );