sections
241 rows where references = "[]" sorted by content
This data as json, CSV (advanced)
Suggested facets: page
id | page | ref | title | content ▼ | breadcrumbs | references |
---|---|---|---|---|---|---|
installation:installation-basic | installation | installation-basic | Basic installation | ["Installation"] | [] | |
installation:installation-advanced | installation | installation-advanced | Advanced installation options | ["Installation"] | [] | |
spatialite:spatialite-installation | spatialite | spatialite-installation | Installation | ["SpatiaLite"] | [] | |
changelog:id1 | changelog | id1 | Changelog | [] | [] | |
changelog:id21 | changelog | id21 | 0.60 (2022-01-13) | ["Changelog"] | [] | |
settings:id1 | settings | id1 | Settings | [] | [] | |
getting_started:getting-started | getting_started | getting-started | Getting started | [] | [] | |
metadata:database-level-metadata | metadata | database-level-metadata | Database-level metadata | "Database-level" metadata refers to fields that can be specified for each database in a Datasette instance. These attributes should be listed under a database inside the "databases" field. The following are the full list of allowed database-level metadata fields: source source_url license license_url about about_url | ["Metadata", "Metadata reference"] | [] |
metadata:table-level-metadata | metadata | table-level-metadata | Table-level metadata | "Table-level" metadata refers to fields that can be specified for each table in a Datasette instance. These attributes should be listed under a specific table using the "tables" field. The following are the full list of allowed table-level metadata fields: source source_url license license_url about about_url hidden sort/sort_desc size sortable_columns label_column facets fts_table fts_pk searchmode columns | ["Metadata", "Metadata reference"] | [] |
metadata:top-level-metadata | metadata | top-level-metadata | Top-level metadata | "Top-level" metadata refers to fields that can be specified at the root level of a metadata file. These attributes are meant to describe the entire Datasette instance. The following are the full list of allowed top-level metadata fields: title description description_html license license_url source source_url | ["Metadata", "Metadata reference"] | [] |
metadata:id2 | metadata | id2 | Metadata reference | A full reference of every supported option in a metadata.json or metadata.yaml file. | ["Metadata"] | [] |
changelog:id45 | changelog | id45 | 0.51 (2020-10-31) | A new visual design, plugin hooks for adding navigation options, better handling of binary data, URL building utility methods and better support for running Datasette behind a proxy. | ["Changelog"] | [] |
changelog:id84 | changelog | id84 | 0.29 (2019-07-07) | ASGI, new plugin hooks, facet by date and much, much more... | ["Changelog"] | [] |
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:permissions-alter-table | authentication | permissions-alter-table | alter-table | Actor is allowed to alter a database table. resource - tuple: (string, string) The name of the database, then the name of the table Default deny . | ["Authentication and permissions", "Built-in permissions"] | [] |
authentication:permissions-create-table | authentication | permissions-create-table | create-table | Actor is allowed to create a database table. resource - string The name of the database Default deny . | ["Authentication and permissions", "Built-in permissions"] | [] |
authentication:permissions-delete-row | authentication | permissions-delete-row | delete-row | Actor is allowed to delete rows from a table. resource - tuple: (string, string) The name of the database, then the name of the table Default deny . | ["Authentication and permissions", "Built-in permissions"] | [] |
authentication:permissions-drop-table | authentication | permissions-drop-table | drop-table | Actor is allowed to drop a database table. resource - tuple: (string, string) The name of the database, then the name of the table Default deny . | ["Authentication and permissions", "Built-in permissions"] | [] |
authentication:permissions-insert-row | authentication | permissions-insert-row | insert-row | Actor is allowed to insert rows into a table. resource - tuple: (string, string) The name of the database, then the name of the table Default deny . | ["Authentication and permissions", "Built-in permissions"] | [] |
authentication:permissions-update-row | authentication | permissions-update-row | update-row | Actor is allowed to update rows in a table. resource - tuple: (string, string) The name of the database, then the name of the table Default deny . | ["Authentication and permissions", "Built-in permissions"] | [] |
authentication:permissions-permissions-debug | authentication | permissions-permissions-debug | permissions-debug | Actor is allowed to view the /-/permissions debug page. Default deny . | ["Authentication and permissions", "Built-in permissions"] | [] |
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:id208 | changelog | id208 | 0.11 (2017-11-14) | Added datasette publish now --force option. This calls now with --force - useful as it means you get a fresh copy of datasette even if Now has already cached that docker layer. Enable --cors by default when running in a container. | ["Changelog"] | [] |
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"] | [] |
internals:datasette-add-memory-database | internals | datasette-add-memory-database | .add_memory_database(name) | Adds a shared in-memory database with the specified name: datasette.add_memory_database("statistics") This is a shortcut for the following: from datasette.database import Database datasette.add_database( Database(datasette, memory_name="statistics") ) Using either of these pattern will result in the in-memory database being served at /statistics . | ["Internals for plugins", "Datasette class"] | [] |
settings:setting-allow-facet | settings | setting-allow-facet | allow_facet | Allow users to specify columns they would like to facet on using the ?_facet=COLNAME URL parameter to the table view. This is enabled by default. If disabled, facets will still be displayed if they have been specifically enabled in metadata.json configuration for the table. Here's how to disable this feature: datasette mydatabase.db --setting allow_facet off | ["Settings", "Settings"] | [] |
json_api:tableupsertview | json_api | tableupsertview | Upserting rows | An upsert is an insert or update operation. If a row with a matching primary key already exists it will be updated - otherwise a new row will be inserted. The upsert API is mostly the same shape as the insert API . It requires both the insert-row and update-row permissions. POST /<database>/<table>/-/upsert Content-Type: application/json Authorization: Bearer dstok_<rest-of-token> { "rows": [ { "id": 1, "title": "Updated title for 1", "description": "Updated description for 1" }, { "id": 2, "description": "Updated description for 2", }, { "id": 3, "title": "Item 3", "description": "Description for 3" } ] } Imagine a table with a primary key of id and which already has rows with id values of 1 and 2 . The above example will: Update the row with id of 1 to set both title and description to the new values Update the row with id of 2 to set title to the new value - description will be left unchanged Insert a new row with id of 3 and both title and description set to the new values Similar to /-/insert , a row key with an object can be used instead of a rows array to upsert a single row. If successful, this will return a 200 status code and a {"ok": true} response body. Add "return": true to the request body to return full copies of the affected rows after they have been inserted or updated: { "rows": [ { "id": 1, "title": "Updated title for 1", "description": "Updated descri… | ["JSON API", "The JSON write API"] | [] |
contributing:contributing-debugging | contributing | contributing-debugging | Debugging | Any errors that occur while Datasette is running while display a stack trace on the console. You can tell Datasette to open an interactive pdb debugger session if an error occurs using the --pdb option: datasette --pdb fixtures.db | ["Contributing"] | [] |
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"] | [] |
contributing:contributing-formatting-black | contributing | contributing-formatting-black | Running Black | Black will be installed when you run pip install -e '.[test]' . To test that your code complies with Black, run the following in your root datasette repository checkout: black . --check All done! ✨ 🍰 ✨ 95 files would be left unchanged. If any of your code does not conform to Black you can run this to automatically fix those problems: black . reformatted ../datasette/setup.py All done! ✨ 🍰 ✨ 1 file reformatted, 94 files left unchanged. | ["Contributing", "Code formatting"] | [] |
changelog:signed-values-and-secrets | changelog | signed-values-and-secrets | Signed values and secrets | Both flash messages and user authentication needed a way to sign values and set signed cookies. Two new methods are now available for plugins to take advantage of this mechanism: .sign(value, namespace="default") and .unsign(value, namespace="default") . Datasette will generate a secret automatically when it starts up, but to avoid resetting the secret (and hence invalidating any cookies) every time the server restarts you should set your own secret. You can pass a secret to Datasette using the new --secret option or with a DATASETTE_SECRET environment variable. See Configuring the secret for more details. You can also set a secret when you deploy Datasette using datasette publish or datasette package - see Using secrets with datasette publish . Plugins can now sign values and verify their signatures using the datasette.sign() and datasette.unsign() methods. | ["Changelog", "0.44 (2020-06-11)"] | [] |
metadata:metadata-default-sort | metadata | metadata-default-sort | Setting a default sort order | By default Datasette tables are sorted by primary key. You can over-ride this default for a specific table using the "sort" or "sort_desc" metadata properties: [[[cog metadata_example(cog, { "databases": { "mydatabase": { "tables": { "example_table": { "sort": "created" } } } } }) ]]] [[[end]]] Or use "sort_desc" to sort in descending order: [[[cog metadata_example(cog, { "databases": { "mydatabase": { "tables": { "example_table": { "sort_desc": "created" } } } } }) ]]] [[[end]]] | ["Metadata"] | [] |
settings:setting-sql-time-limit-ms | settings | setting-sql-time-limit-ms | sql_time_limit_ms | By default, queries have a time limit of one second. If a query takes longer than this to run Datasette will terminate the query and return an error. If this time limit is too short for you, you can customize it using the sql_time_limit_ms limit - for example, to increase it to 3.5 seconds: datasette mydatabase.db --setting sql_time_limit_ms 3500 You can optionally set a lower time limit for an individual query using the ?_timelimit=100 query string argument: /my-database/my-table?qSpecies=44&_timelimit=100 This would set the time limit to 100ms for that specific query. This feature is useful if you are working with databases of unknown size and complexity - a query that might make perfect sense for a smaller table could take too long to execute on a table with millions of rows. By setting custom time limits you can execute queries "optimistically" - e.g. give me an exact count of rows matching this query but only if it takes less than 100ms to calculate. | ["Settings", "Settings"] | [] |
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 "] | [] |
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-writable | sql_queries | canned-queries-writable | Writable canned queries | Canned queries by default are read-only. You can use the "write": true key to indicate that a canned query can write to the database. See Access to specific canned queries for details on how to add permission checks to canned queries, using the "allow" key. [[[cog config_example(cog, { "databases": { "mydatabase": { "queries": { "add_name": { "sql": "INSERT INTO names (name) VALUES (:name)", "write": True } } } } }) ]]] [[[end]]] This configuration will create a page at /mydatabase/add_name displaying a form with a name field. Submitting that form will execute the configured INSERT query. You can customize how Datasette represents success and errors using the following optional properties: on_success_message - the message shown when a query is successful on_success_message_sql - alternative to on_success_message : a SQL query that should be executed to generate the message on_success_redirect - the path or URL the user is redirected to on success on_error_message - the message shown when a query throws an error on_error_redirect - the path or URL the user is redirected to on error For example: [[[cog config_example(cog, { "databases": { "mydatabase": { "queries": { "add_name": { "sql": "INSERT INTO names (name) VALUES (:name)", "params": ["name"], "write": Tru… | ["Running SQL queries", "Canned queries"] | [] |
sql_queries:hide-sql | sql_queries | hide-sql | hide_sql | Canned queries default to displaying their SQL query at the top of the page. If the query is extremely long you may want to hide it by default, with a "show" link that can be used to make it visible. Add the "hide_sql": true option to hide the SQL query by default. | ["Running SQL queries", "Canned queries", "Additional canned query options"] | [] |
internals:database-close | internals | database-close | db.close() | Closes all of the open connections to file-backed databases. This is mainly intended to be used by large test suites, to avoid hitting limits on the number of open files. | ["Internals for plugins", "Database class"] | [] |
authentication:permissions-debug-menu | authentication | permissions-debug-menu | debug-menu | Controls if the various debug pages are displayed in the navigation menu. Default deny . | ["Authentication and permissions", "Built-in permissions"] | [] |
performance:performance-inspect | performance | performance-inspect | Using "datasette inspect" | Counting the rows in a table can be a very expensive operation on larger databases. In immutable mode Datasette performs this count only once and caches the results, but this can still cause server startup time to increase by several seconds or more. If you know that a database is never going to change you can precalculate the table row counts once and store then in a JSON file, then use that file when you later start the server. To create a JSON file containing the calculated row counts for a database, use the following: datasette inspect data.db --inspect-file=counts.json Then later you can start Datasette against the counts.json file and use it to skip the row counting step and speed up server startup: datasette -i data.db --inspect-file=counts.json You need to use the -i immutable mode against the database file here or the counts from the JSON file will be ignored. You will rarely need to use this optimization in every-day use, but several of the datasette publish commands described in Publishing data use this optimization for better performance when deploying a database file to a hosting provider. | ["Performance and caching"] | [] |
cli-reference:cli-help-create-token-help | cli-reference | cli-help-create-token-help | datasette create-token | Create a signed API token, see datasette create-token . [[[cog help(["create-token", "--help"]) ]]] Usage: datasette create-token [OPTIONS] ID Create a signed API token for the specified actor ID Example: datasette create-token root --secret mysecret To allow only "view-database-download" for all databases: datasette create-token root --secret mysecret \ --all view-database-download To allow "create-table" against a specific database: datasette create-token root --secret mysecret \ --database mydb create-table To allow "insert-row" against a specific table: datasette create-token root --secret myscret \ --resource mydb mytable insert-row Restricted actions can be specified multiple times using multiple --all, --database, and --resource options. Add --debug to see a decoded version of the token. Options: --secret TEXT Secret used for signing the API tokens [required] -e, --expires-after INTEGER Token should expire after this many seconds -a, --all ACTION Restrict token to this action -d, --database DB ACTION Restrict token to this action on this database -r, --resource DB RESOURCE ACTION Restrict token to this action on this database resource (a table, SQL view or named query) --debug Show decoded token --plugins-dir DIRECTORY Path to directory containing custom plugins --help Show this message and exit. [[[end]]] | ["CLI reference"] | [] |
custom_templates:custom-pages-headers | custom_templates | custom-pages-headers | Custom headers and status codes | Custom pages default to being served with a content-type of text/html; charset=utf-8 and a 200 status code. You can change these by calling a custom function from within your template. For example, to serve a custom page with a 418 I'm a teapot HTTP status code, create a file in pages/teapot.html containing the following: {{ custom_status(418) }} <html> <head><title>Teapot</title></head> <body> I'm a teapot </body> </html> To serve a custom HTTP header, add a custom_header(name, value) function call. For example: {{ custom_status(418) }} {{ custom_header("x-teapot", "I am") }} <html> <head><title>Teapot</title></head> <body> I'm a teapot </body> </html> You can verify this is working using curl like this: curl -I 'http://127.0.0.1:8001/teapot' HTTP/1.1 418 date: Sun, 26 Apr 2020 18:38:30 GMT server: uvicorn x-teapot: I am content-type: text/html; charset=utf-8 | ["Custom pages and templates"] | [] |
metadata:id1 | metadata | id1 | Metadata | Data loves metadata. Any time you run Datasette you can optionally include a YAML or JSON file with metadata about your databases and tables. Datasette will then display that information in the web UI. Run Datasette like this: datasette database1.db database2.db --metadata metadata.yaml Your metadata.yaml file can look something like this: [[[cog from metadata_doc import metadata_example metadata_example(cog, { "title": "Custom title for your index page", "description": "Some description text can go here", "license": "ODbL", "license_url": "https://opendatacommons.org/licenses/odbl/", "source": "Original Data Source", "source_url": "http://example.com/" }) ]]] [[[end]]] Choosing YAML over JSON adds support for multi-line strings and comments. The above metadata will be displayed on the index page of your Datasette-powered site. The source and license information will also be included in the footer of every page served by Datasette. Any special HTML characters in description will be escaped. If you want to include HTML in your description, you can use a description_html property instead. | [] | [] |
metadata:metadata-sortable-columns | metadata | metadata-sortable-columns | Setting which columns can be used for sorting | Datasette allows any column to be used for sorting by default. If you need to control which columns are available for sorting you can do so using the optional sortable_columns key: [[[cog metadata_example(cog, { "databases": { "database1": { "tables": { "example_table": { "sortable_columns": [ "height", "weight" ] } } } } }) ]]] [[[end]]] This will restrict sorting of example_table to just the height and weight columns. You can also disable sorting entirely by setting "sortable_columns": [] You can use sortable_columns to enable specific sort orders for a view called name_of_view in the database my_database like so: [[[cog metadata_example(cog, { "databases": { "my_database": { "tables": { "name_of_view": { "sortable_columns": [ "clicks", "impressions" ] } } } } }) ]]] [[[end]]] | ["Metadata"] | [] |
deploying:deploying-fundamentals | deploying | deploying-fundamentals | Deployment fundamentals | Datasette can be deployed as a single datasette process that listens on a port. Datasette is not designed to be run as root, so that process should listen on a higher port such as port 8000. If you want to serve Datasette on port 80 (the HTTP default port) or port 443 (for HTTPS) you should run it behind a proxy server, such as nginx, Apache or HAProxy. The proxy server can listen on port 80/443 and forward traffic on to Datasette. | ["Deploying Datasette"] | [] |
json_api:expand-foreign-keys | json_api | expand-foreign-keys | Expanding foreign key references | Datasette can detect foreign key relationships and resolve those references into labels. The HTML interface does this by default for every detected foreign key column - you can turn that off using ?_labels=off . You can request foreign keys be expanded in JSON using the _labels=on or _label=COLUMN special query string parameters. Here's what an expanded row looks like: [ { "rowid": 1, "TreeID": 141565, "qLegalStatus": { "value": 1, "label": "Permitted Site" }, "qSpecies": { "value": 1, "label": "Myoporum laetum :: Myoporum" }, "qAddress": "501X Baker St", "SiteOrder": 1 } ] The column in the foreign key table that is used for the label can be specified in metadata.json - see Specifying the label column for a table . | ["JSON API"] | [] |
javascript_plugins:id1 | javascript_plugins | id1 | JavaScript plugins | Datasette can run custom JavaScript in several different ways: Datasette plugins written in Python can use the extra_js_urls() or extra_body_script() plugin hooks to inject JavaScript into a page Datasette instances with custom templates can include additional JavaScript in those templates The extra_js_urls key in datasette.yaml can be used to include extra JavaScript There are no limitations on what this JavaScript can do. It is executed directly by the browser, so it can manipulate the DOM, fetch additional data and do anything else that JavaScript is capable of. Custom JavaScript has security implications, especially for authenticated Datasette instances where the JavaScript might run in the context of the authenticated user. It's important to carefully review any JavaScript you run in your Datasette instance. | [] | [] |
custom_templates:customization-static-files | custom_templates | customization-static-files | Serving static files | Datasette can serve static files for you, using the --static option. Consider the following directory structure: metadata.json static-files/styles.css static-files/app.js You can start Datasette using --static assets:static-files/ to serve those files from the /assets/ mount point: datasette --config datasette.yaml --static assets:static-files/ --memory The following URLs will now serve the content from those CSS and JS files: http://localhost:8001/assets/styles.css http://localhost:8001/assets/app.js You can reference those files from datasette.yaml like this, see custom CSS and JavaScript for more details: [[[cog from metadata_doc import config_example config_example(cog, """ extra_css_urls: - /assets/styles.css extra_js_urls: - /assets/app.js """) ]]] [[[end]]] | ["Custom pages and templates"] | [] |
metadata:metadata-page-size | metadata | metadata-page-size | Setting a custom page size | Datasette defaults to displaying 100 rows per page, for both tables and views. You can change this default page size on a per-table or per-view basis using the "size" key in metadata.json : [[[cog metadata_example(cog, { "databases": { "mydatabase": { "tables": { "example_table": { "size": 10 } } } } }) ]]] [[[end]]] This size can still be over-ridden by passing e.g. ?_size=50 in the query string. | ["Metadata"] | [] |
plugins:plugins-datasette-load-plugins | plugins | plugins-datasette-load-plugins | Controlling which plugins are loaded | Datasette defaults to loading every plugin that is installed in the same virtual environment as Datasette itself. You can set the DATASETTE_LOAD_PLUGINS environment variable to a comma-separated list of plugin names to load a controlled subset of plugins instead. For example, to load just the datasette-vega and datasette-cluster-map plugins, set DATASETTE_LOAD_PLUGINS to datasette-vega,datasette-cluster-map : export DATASETTE_LOAD_PLUGINS='datasette-vega,datasette-cluster-map' datasette mydb.db Or: DATASETTE_LOAD_PLUGINS='datasette-vega,datasette-cluster-map' \ datasette mydb.db To disable the loading of all additional plugins, set DATASETTE_LOAD_PLUGINS to an empty string: export DATASETTE_LOAD_PLUGINS='' datasette mydb.db A quick way to test this setting is to use it with the datasette plugins command: DATASETTE_LOAD_PLUGINS='datasette-vega' datasette plugins This should output the following: [ { "name": "datasette-vega", "static": true, "templates": false, "version": "0.6.2", "hooks": [ "extra_css_urls", "extra_js_urls" ] } ] | ["Plugins"] | [] |
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. | [] | [] |
javascript_plugins:javascript-datasette-init | javascript_plugins | javascript-datasette-init | The datasette_init event | Datasette emits a custom event called datasette_init when the page is loaded. This event is dispatched on the document object, and includes a detail object with a reference to the datasetteManager object. Your JavaScript code can listen out for this event using document.addEventListener() like this: document.addEventListener("datasette_init", function (evt) { const manager = evt.detail; console.log("Datasette version:", manager.VERSION); }); | ["JavaScript plugins"] | [] |
authentication:authentication-ds-actor | authentication | authentication-ds-actor | The ds_actor cookie | Datasette includes a default authentication plugin which looks for a signed ds_actor cookie containing a JSON actor dictionary. This is how the root actor mechanism works. Authentication plugins can set signed ds_actor cookies themselves like so: response = Response.redirect("/") response.set_cookie( "ds_actor", datasette.sign({"a": {"id": "cleopaws"}}, "actor"), ) Note that you need to pass "actor" as the namespace to .sign(value, namespace="default") . The shape of data encoded in the cookie is as follows: { "a": {... actor ...} } | ["Authentication and permissions"] | [] |
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"] | [] |
events:id1 | events | id1 | Events | Datasette includes a mechanism for tracking events that occur while the software is running. This is primarily intended to be used by plugins, which can both trigger events and listen for events. The core Datasette application triggers events when certain things happen. This page describes those events. Plugins can listen for events using the track_event(datasette, event) plugin hook, which will be called with instances of the following classes - or additional classes registered by other plugins . class datasette.events. LoginEvent actor : dict | None Event name: login A user (represented by event.actor ) has logged in. class datasette.events. LogoutEvent actor : dict | None Event name: logout A user (represented by event.actor ) has logged out. class datasette.events. CreateTokenEvent actor : dict | None expires_after : int | None restrict_all : list restrict_database : dict restrict_resource : dict Event name: create-token A user created an API token. Variables expires_after -- Number of seconds after which this token will expire. restrict_all -- Restricted permissions for this token. restrict_database -- Restricted database permissions for this token. … | [] | [] |
plugin_hooks:plugin-event-tracking | plugin_hooks | plugin-event-tracking | Event tracking | Datasette includes an internal mechanism for tracking notable events. This can be used for analytics, but can also be used by plugins that want to listen out for when key events occur (such as a table being created) and take action in response. Plugins can register to receive events using the track_event plugin hook. They can also define their own events for other plugins to receive using the register_events() plugin hook , combined with calls to the datasette.track_event() internal method . | ["Plugin hooks"] | [] |
introspection:id1 | introspection | id1 | Introspection | Datasette includes some pages and JSON API endpoints for introspecting the current instance. These can be used to understand some of the internals of Datasette and to see how a particular instance has been configured. Each of these pages can be viewed in your browser. Add .json to the URL to get back the contents as JSON. | [] | [] |
publish:publishing | publish | publishing | Publishing data | Datasette includes tools for publishing and deploying your data to the internet. The datasette publish command will deploy a new Datasette instance containing your databases directly to a Heroku or Google Cloud hosting account. You can also use datasette package to create a Docker image that bundles your databases together with the datasette application that is used to serve them. | [] | [] |
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 . | [] | [] |
internals:internals-internal | internals | internals-internal | Datasette's internal database | Datasette maintains an "internal" SQLite database used for configuration, caching, and storage. Plugins can store configuration, settings, and other data inside this database. By default, Datasette will use a temporary in-memory SQLite database as the internal database, which is created at startup and destroyed at shutdown. Users of Datasette can optionally pass in a --internal flag to specify the path to a SQLite database to use as the internal database, which will persist internal data across Datasette instances. Datasette maintains tables called catalog_databases , catalog_tables , catalog_columns , catalog_indexes , catalog_foreign_keys with details of the attached databases and their schemas. These tables should not be considered a stable API - they may change between Datasette releases. The internal database is not exposed in the Datasette application by default, which means private data can safely be stored without worry of accidentally leaking information through the default Datasette interface and API. However, other plugins do have full read and write access to the internal database. Plugins can access this database by calling internal_db = datasette.get_internal_database() and then executing queries using the Database API . Plugin authors are asked to practice good etiquette when using the internal database, as all plugins use the same database to store data. For example: Use a unique prefix when creating tables, indices, and triggers in the internal database. If your plugin is called datasette-xyz , then prefix names with datasette_xyz_* . Avoid long-running write statements that may stall or block other plugins that are trying to write at the same time. Use temporary tables or shared in-memory attached databases when possible. … | ["Internals for plugins"] | [] |
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. | [] | [] |
configuration:configuration-reference-plugins | configuration | configuration-reference-plugins | Plugin configuration | Datasette plugins often require configuration. This plugin configuration should be placed in plugins keys inside datasette.yaml . Most plugins are configured at the top-level of the file, using the plugins key: [[[cog from metadata_doc import config_example import textwrap config_example(cog, textwrap.dedent( """ # inside datasette.yaml plugins: datasette-my-plugin: key: my_value """).strip() ) ]]] [[[end]]] Some plugins can be configured at the database or table level. These should use a plugins key nested under the appropriate place within the databases object: [[[cog from metadata_doc import config_example import textwrap config_example(cog, textwrap.dedent( """ # inside datasette.yaml databases: my_database: # plugin configuration for the my_database database plugins: datasette-my-plugin: key: my_value my_other_database: tables: my_table: # plugin configuration for the my_table table inside the my_other_database database plugins: datasette-my-plugin: key: my_value """).strip() ) ]]] [[[end]]] | ["Configuration", null] | [] |
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"] | [] |
json_api:id1 | json_api | id1 | JSON API | Datasette provides a JSON API for your SQLite databases. Anything you can do through the Datasette user interface can also be accessed as JSON via the API. To access the API for a page, either click on the .json link on that page or edit the URL and add a .json extension to it. | [] | [] |
custom_templates:customization | custom_templates | customization | Custom pages and templates | Datasette provides a number of ways of customizing the way data is displayed. | [] | [] |
json_api:json-api-write | json_api | json-api-write | The JSON write API | Datasette provides a write API for JSON data. This is a POST-only API that requires an authenticated API token, see API Tokens . The token will need to have the specified Permissions . | ["JSON API"] | [] |
settings:setting-max-returned-rows | settings | setting-max-returned-rows | max_returned_rows | Datasette returns a maximum of 1,000 rows of data at a time. If you execute a query that returns more than 1,000 rows, Datasette will return the first 1,000 and include a warning that the result set has been truncated. You can use OFFSET/LIMIT or other methods in your SQL to implement pagination if you need to return more than 1,000 rows. You can increase or decrease this limit like so: datasette mydatabase.db --setting max_returned_rows 2000 | ["Settings", "Settings"] | [] |
performance:performance | performance | performance | Performance and caching | Datasette runs on top of SQLite, and SQLite has excellent performance. For small databases almost any query should return in just a few milliseconds, and larger databases (100s of MBs or even GBs of data) should perform extremely well provided your queries make sensible use of database indexes. That said, there are a number of tricks you can use to improve Datasette's performance. | [] | [] |
settings:using-setting | settings | using-setting | Using --setting | Datasette supports a number of settings. These can be set using the --setting name value option to datasette serve . You can set multiple settings at once like this: datasette mydatabase.db \ --setting default_page_size 50 \ --setting sql_time_limit_ms 3500 \ --setting max_returned_rows 2000 Settings can also be specified in the database.yaml configuration file . | ["Settings"] | [] |
sql_queries:sql | sql_queries | sql | Running SQL queries | Datasette treats SQLite database files as read-only and immutable. This means it is not possible to execute INSERT or UPDATE statements using Datasette, which allows us to expose SELECT statements to the outside world without needing to worry about SQL injection attacks. The easiest way to execute custom SQL against Datasette is through the web UI. The database index page includes a SQL editor that lets you run any SELECT query you like. You can also construct queries using the filter interface on the tables page, then click "View and edit SQL" to open that query in the custom SQL editor. Note that this interface is only available if the execute-sql permission is allowed. See Controlling the ability to execute arbitrary SQL . Any Datasette SQL query is reflected in the URL of the page, allowing you to bookmark them, share them with others and navigate through previous queries using your browser back button. You can also retrieve the results of any query as JSON by adding .json to the base URL. | [] | [] |
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"] | [] |
configuration:configuration-reference-permissions | configuration | configuration-reference-permissions | Permissions configuration | Datasette's authentication and permissions system can also be configured using datasette.yaml . Here is a simple example: [[[cog from metadata_doc import config_example import textwrap config_example(cog, textwrap.dedent( """ # Instance is only available to users 'sharon' and 'percy': allow: id: - sharon - percy # Only 'percy' is allowed access to the accounting database: databases: accounting: allow: id: percy """).strip() ) ]]] [[[end]]] Access permissions in datasette.yaml has the full details. | ["Configuration", null] | [] |
metadata:label-columns | metadata | label-columns | Specifying the label column for a table | Datasette's HTML interface attempts to display foreign key references as labelled hyperlinks. By default, it looks for referenced tables that only have two columns: a primary key column and one other. It assumes that the second column should be used as the link label. If your table has more than two columns you can specify which column should be used for the link label with the label_column property: [[[cog metadata_example(cog, { "databases": { "database1": { "tables": { "example_table": { "label_column": "title" } } } } }) ]]] [[[end]]] | ["Metadata"] | [] |
sql_queries:id2 | sql_queries | id2 | Pagination | Datasette's default table pagination is designed to be extremely efficient. SQL OFFSET/LIMIT pagination can have a significant performance penalty once you get into multiple thousands of rows, as each page still requires the database to scan through every preceding row to find the correct offset. When paginating through tables, Datasette instead orders the rows in the table by their primary key and performs a WHERE clause against the last seen primary key for the previous page. For example: select rowid, * from Tree_List where rowid > 200 order by rowid limit 101 This represents page three for this particular table, with a page size of 100. Note that we request 101 items in the limit clause rather than 100. This allows us to detect if we are on the last page of the results: if the query returns less than 101 rows we know we have reached the end of the pagination set. Datasette will only return the first 100 rows - the 101st is used purely to detect if there should be another page. Since the where clause acts against the index on the primary key, the query is extremely fast even for records that are a long way into the overall pagination set. | ["Running SQL queries"] | [] |
facets:suggested-facets | facets | suggested-facets | Suggested facets | Datasette's table UI will suggest facets for the user to apply, based on the following criteria: For the currently filtered data are there any columns which, if applied as a facet... Will return 30 or less unique options Will return more than one unique option Will return less unique options than the total number of filtered rows And the query used to evaluate this criteria can be completed in under 50ms That last point is particularly important: Datasette runs a query for every column that is displayed on a page, which could get expensive - so to avoid slow load times it sets a time limit of just 50ms for each of those queries. This means suggested facets are unlikely to appear for tables with millions of records in them. | ["Facets"] | [] |
settings:setting-default-cache-ttl | settings | setting-default-cache-ttl | default_cache_ttl | Default HTTP caching max-age header in seconds, used for Cache-Control: max-age=X . Can be over-ridden on a per-request basis using the ?_ttl= query string parameter. Set this to 0 to disable HTTP caching entirely. Defaults to 5 seconds. datasette mydatabase.db --setting default_cache_ttl 60 | ["Settings", "Settings"] | [] |
internals:internals-utils-derive-named-parameters | internals | internals-utils-derive-named-parameters | derive_named_parameters(db, sql) | Derive the list of named parameters referenced in a SQL query, using an explain query executed against the provided database. async datasette.utils. derive_named_parameters db : Database sql : str List [ str ] Given a SQL statement, return a list of named parameters that are used in the statement e.g. for select * from foo where id=:id this would return ["id"] | ["Internals for plugins", "The datasette.utils module"] | [] |
settings:setting-allow-csv-stream | settings | setting-allow-csv-stream | allow_csv_stream | Enables the CSV export feature where an entire table (potentially hundreds of thousands of rows) can be exported as a single CSV file. This is turned on by default - you can turn it off like this: datasette mydatabase.db --setting allow_csv_stream off | ["Settings", "Settings"] | [] |
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"] | [] |
internals:database-execute | internals | database-execute | await db.execute(sql, ...) | Executes a SQL query against the database and returns the resulting rows (see Results ). sql - string (required) The SQL query to execute. This can include ? or :named parameters. params - list or dict A list or dictionary of values to use for the parameters. List for ? , dictionary for :named . truncate - boolean Should the rows returned by the query be truncated at the maximum page size? Defaults to True , set this to False to disable truncation. custom_time_limit - integer ms A custom time limit for this query. This can be set to a lower value than the Datasette configured default. If a query takes longer than this it will be terminated early and raise a dataette.database.QueryInterrupted exception. page_size - integer Set a custom page size for truncation, over-riding the configured Datasette default. log_sql_errors - boolean Should any SQL errors be logged to the console in addition to being raised as an error? Defaults to True . | ["Internals for plugins", "Database class"] | [] |
internals:database-execute-fn | internals | database-execute-fn | await db.execute_fn(fn) | Executes a given callback function against a read-only database connection running in a thread. The function will be passed a SQLite connection, and the return value from the function will be returned by the await . Example usage: def get_version(conn): return conn.execute( "select sqlite_version()" ).fetchall()[0][0] version = await db.execute_fn(get_version) | ["Internals for plugins", "Database class"] | [] |
authentication:authentication-permissions-other | authentication | authentication-permissions-other | Other permissions in | For all other permissions, you can use one or more "permissions" blocks in your datasette.yaml configuration file. To grant access to the permissions debug tool to all signed in users, you can grant permissions-debug to any actor with an id matching the wildcard * by adding this a the root of your configuration: [[[cog config_example(cog, """ permissions: debug-menu: id: '*' """) ]]] [[[end]]] To grant create-table to the user with id of editor for the docs database: [[[cog config_example(cog, """ databases: docs: permissions: create-table: id: editor """) ]]] [[[end]]] And for insert-row against the reports table in that docs database: [[[cog config_example(cog, """ databases: docs: tables: reports: permissions: insert-row: id: editor """) ]]] [[[end]]] The permissions debug tool can be useful for helping test permissions that you have configured in this way. | ["Authentication and permissions"] | [] |
settings:setting-force-https-urls | settings | setting-force-https-urls | force_https_urls | Forces self-referential URLs in the JSON output to always use the https:// protocol. This is useful for cases where the application itself is hosted using HTTP but is served to the outside world via a proxy that enables HTTPS. datasette mydatabase.db --setting force_https_urls 1 | ["Settings", "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"] | [] |
spatialite:spatial-indexing-latitude-longitude-columns | spatialite | spatial-indexing-latitude-longitude-columns | Spatial indexing latitude/longitude columns | Here's a recipe for taking a table with existing latitude and longitude columns, adding a SpatiaLite POINT geometry column to that table, populating the new column and then populating a spatial index: import sqlite3 conn = sqlite3.connect("museums.db") # Lead the spatialite extension: conn.enable_load_extension(True) conn.load_extension("/usr/local/lib/mod_spatialite.dylib") # Initialize spatial metadata for this database: conn.execute("select InitSpatialMetadata(1)") # Add a geometry column called point_geom to our museums table: conn.execute( "SELECT AddGeometryColumn('museums', 'point_geom', 4326, 'POINT', 2);" ) # Now update that geometry column with the lat/lon points conn.execute( """ UPDATE museums SET point_geom = GeomFromText('POINT('||"longitude"||' '||"latitude"||')',4326); """ ) # Now add a spatial index to that column conn.execute( 'select CreateSpatialIndex("museums", "point_geom");' ) # If you don't commit your changes will not be persisted: conn.commit() conn.close() | ["SpatiaLite"] | [] |
plugins:plugins-installing | plugins | plugins-installing | Installing plugins | If a plugin has been packaged for distribution using setuptools you can use the plugin by installing it alongside Datasette in the same virtual environment or Docker container. You can install plugins using the datasette install command: datasette install datasette-vega You can uninstall plugins with datasette uninstall : datasette uninstall datasette-vega You can upgrade plugins with datasette install --upgrade or datasette install -U : datasette install -U datasette-vega This command can also be used to upgrade Datasette itself to the latest released version: datasette install -U datasette You can install multiple plugins at once by listing them as lines in a requirements.txt file like this: datasette-vega datasette-cluster-map Then pass that file to datasette install -r : datasette install -r requirements.txt The install and uninstall commands are thin wrappers around pip install and pip uninstall , which ensure that they run pip in the same virtual environment as Datasette itself. | ["Plugins"] | [] |
testing_plugins:testing-plugins-pdb | testing_plugins | testing-plugins-pdb | Using pdb for errors thrown inside Datasette | If an exception occurs within Datasette itself during a test, the response returned to your plugin will have a response.status_code value of 500. You can add pdb=True to the Datasette constructor to drop into a Python debugger session inside your test run instead of getting back a 500 response code. This is equivalent to running the datasette command-line tool with the --pdb option. Here's what that looks like in a test function: def test_that_opens_the_debugger_or_errors(): ds = Datasette([db_path], pdb=True) response = await ds.client.get("/") If you use this pattern you will need to run pytest with the -s option to avoid capturing stdin/stdout in order to interact with the debugger prompt. | ["Testing plugins"] | [] |
internals:database-hash | internals | database-hash | db.hash | If the database was opened in immutable mode, this property returns the 64 character SHA-256 hash of the database contents as a string. Otherwise it returns None . | ["Internals for plugins", "Database class"] | [] |
settings:setting-base-url | settings | setting-base-url | base_url | If you are running Datasette behind a proxy, it may be useful to change the root path used for the Datasette instance. For example, if you are sending traffic from https://www.example.com/tools/datasette/ through to a proxied Datasette instance you may wish Datasette to use /tools/datasette/ as its root URL. You can do that like so: datasette mydatabase.db --setting base_url /tools/datasette/ | ["Settings", "Settings"] | [] |
performance:performance-immutable-mode | performance | performance-immutable-mode | Immutable mode | If you can be certain that a SQLite database file will not be changed by another process you can tell Datasette to open that file in immutable mode . Doing so will disable all locking and change detection, which can result in improved query performance. This also enables further optimizations relating to HTTP caching, described below. To open a file in immutable mode pass it to the datasette command using the -i option: datasette -i data.db When you open a file in immutable mode like this Datasette will also calculate and cache the row counts for each table in that database when it first starts up, further improving performance. | ["Performance and caching"] | [] |
installation:id1 | installation | id1 | Installation | If you just want to try Datasette out you don't need to install anything: see Try Datasette without installing anything using Glitch There are two main options for installing Datasette. You can install it directly on to your machine, or you can install it using Docker. If you want to start making contributions to the Datasette project by installing a copy that lets you directly modify the code, take a look at our guide to Setting up a development environment . Basic installation Datasette Desktop for Mac Using Homebrew Using pip Advanced installation options Using pipx Installing plugins using pipx Upgrading packages using pipx Using Docker Loading SpatiaLite Installing plugins A note about extensions | [] | [] |
json_api:json-api-cors | json_api | json-api-cors | Enabling CORS | If you start Datasette with the --cors option, each JSON endpoint will be served with the following additional HTTP headers: [[[cog from datasette.utils import add_cors_headers import textwrap headers = {} add_cors_headers(headers) output = "\n".join("{}: {}".format(k, v) for k, v in headers.items()) cog.out("\n::\n\n") cog.out(textwrap.indent(output, ' ')) cog.out("\n\n") ]]] Access-Control-Allow-Origin: * Access-Control-Allow-Headers: Authorization, Content-Type Access-Control-Expose-Headers: Link Access-Control-Allow-Methods: GET, POST, HEAD, OPTIONS Access-Control-Max-Age: 3600 [[[end]]] This allows JavaScript running on any domain to make cross-origin requests to interact with the Datasette API. If you start Datasette without the --cors option only JavaScript running on the same domain as Datasette will be able to access the API. Here's how to serve data.db with CORS enabled: datasette data.db --cors | ["JSON API"] | [] |
changelog:v0-29-medium-changes | changelog | v0-29-medium-changes | Easier custom templates for table rows | If you want to customize the display of individual table rows, you can do so using a _table.html template include that looks something like this: {% for row in display_rows %} <div> <h2>{{ row["title"] }}</h2> <p>{{ row["description"] }}<lp> <p>Category: {{ row.display("category_id") }}</p> </div> {% endfor %} This is a backwards incompatible change . If you previously had a custom template called _rows_and_columns.html you need to rename it to _table.html . See Custom templates for full details. | ["Changelog", "0.29 (2019-07-07)"] | [] |
plugin_hooks:plugin-register-permissions | plugin_hooks | plugin-register-permissions | register_permissions(datasette) | If your plugin needs to register additional permissions unique to that plugin - upload-csvs for example - you can return a list of those permissions from this hook. from datasette import hookimpl, Permission @hookimpl def register_permissions(datasette): return [ Permission( name="upload-csvs", abbr=None, description="Upload CSV files", takes_database=True, takes_resource=False, default=False, ) ] The fields of the Permission class are as follows: name - string The name of the permission, e.g. upload-csvs . This should be unique across all plugins that the user might have installed, so choose carefully. abbr - string or None An abbreviation of the permission, e.g. uc . This is optional - you can set it to None if you do not want to pick an abbreviation. Since this needs to be unique across all installed plugins it's best not to specify an abbreviation at all. If an abbreviation is provided it will be used when creating restricted signed API tokens. description - string or None A human-readable description of what the permission lets you do. Should make sense as the second part of a sentence that starts "A user with this permission can ...". takes_database - boolean True if this permission can be granted on a per-database basis, False if it is only valid at the overall Datasette instance level. takes_resource - boolean … | ["Plugin hooks"] | [] |
changelog:id44 | changelog | id44 | 0.51.1 (2020-10-31) | Improvements to the new Binary data documentation page. | ["Changelog"] | [] |
internals:internals-response-asgi-send | internals | internals-response-asgi-send | Returning a response with .asgi_send(send) | In most cases you will return Response objects from your own view functions. You can also use a Response instance to respond at a lower level via ASGI, for example if you are writing code that uses the asgi_wrapper(datasette) hook. Create a Response object and then use await response.asgi_send(send) , passing the ASGI send function. For example: async def require_authorization(scope, receive, send): response = Response.text( "401 Authorization Required", headers={ "www-authenticate": 'Basic realm="Datasette", charset="UTF-8"' }, status=401, ) await response.asgi_send(send) | ["Internals for plugins", "Response class"] | [] |
settings:setting-truncate-cells-html | settings | setting-truncate-cells-html | truncate_cells_html | In the HTML table view, truncate any strings that are longer than this value. The full value will still be available in CSV, JSON and on the individual row HTML page. Set this to 0 to disable truncation. datasette mydatabase.db --setting truncate_cells_html 0 | ["Settings", "Settings"] | [] |
internals:internals-database | internals | internals-database | Database class | Instances of the Database class can be used to execute queries against attached SQLite databases, and to run introspection against their schemas. | ["Internals for plugins"] | [] |
json_api:tablecreateview-example | json_api | tablecreateview-example | Creating a table from example data | Instead of specifying columns directly you can instead pass a single example row or a list of rows . Datasette will create a table with a schema that matches those rows and insert them for you: POST /<database>/-/create Content-Type: application/json Authorization: Bearer dstok_<rest-of-token> { "table": "creatures", "rows": [ { "id": 1, "name": "Tarantula" }, { "id": 2, "name": "Kākāpō" } ], "pk": "id" } Doing this requires both the create-table and insert-row permissions. The 201 response here will be similar to the columns form, but will also include the number of rows that were inserted as row_count : { "ok": true, "database": "data", "table": "creatures", "table_url": "http://127.0.0.1:8001/data/creatures", "table_api_url": "http://127.0.0.1:8001/data/creatures.json", "schema": "CREATE TABLE [creatures] (\n [id] INTEGER PRIMARY KEY,\n [name] TEXT\n)", "row_count": 2 } You can call the create endpoint multiple times for the same table provided you are specifying the table using the rows or row option. New rows will be inserted into the table each time. This means you can use this API if you are unsure if the relevant table has been created yet. If you pass a row to the create endpoint with a primary key that already exists you will get an error that looks like this: { "ok": false, "errors": [ "UNIQUE constraint failed: creatures.id" ] } You can avoid this error by passing the same "ignore": true or "replace": true options to the create endpoint as you can to the insert endpoint . To use the "replace": true option you will also need the update-row permission. Pass "alter": true to automatically add any missing columns to t… | ["JSON API", "The JSON write API"] | [] |
javascript_plugins:id2 | javascript_plugins | id2 | JavaScript plugin objects | JavaScript plugins are blocks of code that can be registered with Datasette using the registerPlugin() method on the datasetteManager object. The implementation object passed to this method should include a version key defining the plugin version, and one or more of the following named functions providing the implementation of the plugin: | ["JavaScript 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 );