rowid,title,content,sections_fts,rank 795,datasette package,"If you have docker installed (e.g. using Docker for Mac ) you can use the datasette package command to create a new Docker image in your local repository containing the datasette app bundled together with one or more SQLite databases: datasette package mydatabase.db Here's example output for the package command: datasette package parlgov.db --extra-options=""--setting sql_time_limit_ms 2500"" Sending build context to Docker daemon 4.459MB Step 1/7 : FROM python:3.11.0-slim-bullseye ---> 79e1dc9af1c1 Step 2/7 : COPY . /app ---> Using cache ---> cd4ec67de656 Step 3/7 : WORKDIR /app ---> Using cache ---> 139699e91621 Step 4/7 : RUN pip install datasette ---> Using cache ---> 340efa82bfd7 Step 5/7 : RUN datasette inspect parlgov.db --inspect-file inspect-data.json ---> Using cache ---> 5fddbe990314 Step 6/7 : EXPOSE 8001 ---> Using cache ---> 8e83844b0fed Step 7/7 : CMD datasette serve parlgov.db --port 8001 --inspect-file inspect-data.json --setting sql_time_limit_ms 2500 ---> Using cache ---> 1bd380ea8af3 Successfully built 1bd380ea8af3 You can now run the resulting container like so: docker run -p 8081:8001 1bd380ea8af3 This exposes port 8001 inside the container as port 8081 on your host machine, so you can access the application at http://localhost:8081/ You can customize the port that is exposed by the container using the --port option: datasette package mydatabase.db --port 8080 A full list of options can be seen by running datasette package --help : See datasette package for the full list of options for this command.",508, 794,Custom metadata and plugins,"datasette publish accepts a number of additional options which can be used to further customize your Datasette instance. You can define your own Metadata and deploy that with your instance like so: datasette publish cloudrun --service=my-service mydatabase.db -m metadata.json If you just want to set the title, license or source information you can do that directly using extra options to datasette publish : datasette publish cloudrun mydatabase.db --service=my-service \ --title=""Title of my database"" \ --source=""Where the data originated"" \ --source_url=""http://www.example.com/"" You can also specify plugins you would like to install. For example, if you want to include the datasette-vega visualization plugin you can use the following: datasette publish cloudrun mydatabase.db --service=my-service --install=datasette-vega If a plugin has any Secret configuration values you can use the --plugin-secret option to set those secrets at publish time. For example, using Heroku with datasette-auth-github you might run the following command: datasette publish heroku my_database.db \ --name my-heroku-app-demo \ --install=datasette-auth-github \ --plugin-secret datasette-auth-github client_id your_client_id \ --plugin-secret datasette-auth-github client_secret your_client_secret",508, 793,Publishing to Fly,"Fly is a competitively priced Docker-compatible hosting platform that supports running applications in globally distributed data centers close to your end users. You can deploy Datasette instances to Fly using the datasette-publish-fly plugin. pip install datasette-publish-fly datasette publish fly mydatabase.db --app=""my-app"" Consult the datasette-publish-fly README for more details.",508, 792,Publishing to Vercel,"Vercel - previously known as Zeit Now - provides a layer over AWS Lambda to allow for quick, scale-to-zero deployment. You can deploy Datasette instances to Vercel using the datasette-publish-vercel plugin. pip install datasette-publish-vercel datasette publish vercel mydatabase.db --project my-database-project Not every feature is supported: consult the datasette-publish-vercel README for more details.",508, 791,Publishing to Heroku,"To publish your data using Heroku , first create an account there and install and configure the Heroku CLI tool . You can publish one or more databases to Heroku using the following command: datasette publish heroku mydatabase.db This will output some details about the new deployment, including a URL like this one: https://limitless-reef-88278.herokuapp.com/ deployed to Heroku You can specify a custom app name by passing -n my-app-name to the publish command. This will also allow you to overwrite an existing app. Rather than deploying directly you can use the --generate-dir option to output the files that would be deployed to a directory: datasette publish heroku mydatabase.db --generate-dir=/tmp/deploy-this-to-heroku See datasette publish heroku for the full list of options for this command.",508, 790,Publishing to Google Cloud Run,"Google Cloud Run allows you to publish data in a scale-to-zero environment, so your application will start running when the first request is received and will shut down again when traffic ceases. This means you only pay for time spent serving traffic. Cloud Run is a great option for inexpensively hosting small, low traffic projects - but costs can add up for projects that serve a lot of requests. Be particularly careful if your project has tables with large numbers of rows. Search engine crawlers that index a page for every row could result in a high bill. The datasette-block-robots plugin can be used to request search engine crawlers omit crawling your site, which can help avoid this issue. You will first need to install and configure the Google Cloud CLI tools by following these instructions . You can then publish one or more SQLite database files to Google Cloud Run using the following command: datasette publish cloudrun mydatabase.db --service=my-database A Cloud Run service is a single hosted application. The service name you specify will be used as part of the Cloud Run URL. If you deploy to a service name that you have used in the past your new deployment will replace the previous one. If you omit the --service option you will be asked to pick a service name interactively during the deploy. You may need to interact with prompts from the tool. Many of the prompts ask for values that can be set as properties for the Google Cloud SDK if you want to avoid the prompts. For example, the default region for the deployed instance can be set using the command: gcloud config set run/region us-central1 You should replace us-central1 with your desired region . Alternately, you can specify the region by setting the CLOUDSDK_RUN_REGION environment variable. Once it has finished it will output a URL like this one: Service [my-service] revision [my-service-00001] has been deployed and is serving traffic at https://my-service-j7hipcg4aq-uc.a.run.app Cloud Run provides a URL on the .run.app domain, but you can also point your own domain or subdomain at your Cloud Run service - see mapping custom domains in the Cloud Run documentation for details. See datasette publish cloudrun for the full list of options for this command.",508, 789,datasette publish,"Once you have created a SQLite database (e.g. using csvs-to-sqlite ) you can deploy it to a hosting account using a single command. You will need a hosting account with Heroku or Google Cloud . Once you have created your account you will need to install and configure the heroku or gcloud command-line tools.",508, 788,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.,508, 787,Using Datasette on your own computer,"First, follow the Installation instructions. Now you can run Datasette against a SQLite file on your computer using the following command: datasette path/to/database.db This will start a web server on port 8001 - visit http://localhost:8001/ to access the web interface. Add -o to open your browser automatically once Datasette has started: datasette path/to/database.db -o Use Chrome on OS X? You can run datasette against your browser history like so: datasette ~/Library/Application\ Support/Google/Chrome/Default/History --nolock The --nolock option ignores any file locks. This is safe as Datasette will open the file in read-only mode. Now visiting http://localhost:8001/History/downloads will show you a web interface to browse your downloads data: http://localhost:8001/History/downloads.json will return that data as JSON: { ""database"": ""History"", ""columns"": [ ""id"", ""current_path"", ""target_path"", ""start_time"", ""received_bytes"", ""total_bytes"", ... ], ""rows"": [ [ 1, ""/Users/simonw/Downloads/DropboxInstaller.dmg"", ""/Users/simonw/Downloads/DropboxInstaller.dmg"", 13097290269022132, 626688, 0, ... ] ] } http://localhost:8001/History/downloads.json?_shape=objects will return that data as JSON in a more convenient format: { ... ""rows"": [ { ""start_time"": 13097290269022132, ""interrupt_reason"": 0, ""hash"": """", ""id"": 1, ""site_url"": """", ""referrer"": ""https://www.dropbox.com/downloading?src=index"", ... } ] }",508, 786,Try Datasette without installing anything with Codespaces,"GitHub Codespaces offers a free browser-based development environment that lets you run a development server without installing any local software. Here's a demo project on GitHub which you can use as the basis for your own experiments: github.com/datasette/datasette-studio The README file in that repository has instructions on how to get started.",508, 785,Datasette in your browser with Datasette Lite,"Datasette Lite is Datasette packaged using WebAssembly so that it runs entirely in your browser, no Python web application server required. You can pass a URL to a CSV, SQLite or raw SQL file directly to Datasette Lite to explore that data in your browser. This example link opens Datasette Lite and loads the SQL Murder Mystery example database from Northwestern University Knight Lab .",508, 784,Follow a tutorial,"Datasette has several tutorials to help you get started with the tool. Try one of the following: Exploring a database with Datasette shows how to use the Datasette web interface to explore a new database. Learn SQL with Datasette introduces SQL, and shows how to use that query language to ask questions of your data. Cleaning data with sqlite-utils and Datasette guides you through using sqlite-utils to turn a CSV file into a database that you can explore using Datasette.",508, 783,Play with a live demo,"The best way to experience Datasette for the first time is with a demo: datasette.io/global-power-plants provides a searchable database of power plants around the world, using data from the World Resources Institude rendered using the datasette-cluster-map plugin. fivethirtyeight.datasettes.com shows Datasette running against over 400 datasets imported from the FiveThirtyEight GitHub repository .",508, 782,Getting started,,508, 781,Contents,"Getting started Play with a live demo Follow a tutorial Datasette in your browser with Datasette Lite Try Datasette without installing anything with Codespaces Using Datasette on your own computer Installation Basic installation 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 Queries configuration Custom CSS and JavaScript Table configuration The Datasette Ecosystem sqlite-utils Dogsheep CLI reference datasette --help datasette serve Environment variables 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 Queries Custom SQL queries Write SQL queries Stored query browsers Table Table fragment Row Schemas Instance schema Database schema Table schema 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 API stability Default representation Error responses Executing custom SQL Different shapes Pagination Special JSON arguments Expanding JSON responses Table JSON responses Row JSON responses Query JSON responses Table autocomplete Table arguments Column filter arguments Special table arguments Expanding foreign key references Discovering the JSON for a page Enabling CORS The JSON write API Executing write SQL Inserting rows Upserting rows Updating a row Deleting a row Creating a table Creating a table from example data Database foreign key targets Table foreign key suggestions Altering tables Setting a column type Dropping tables Running SQL queries Named parameters Views Queries Stored queries Query parameters Additional query options Writable queries Magic parameters JSON API for writable queries Pagination Cross-database queries Authentication and permissions Actors How actors are displayed Using the ""root"" actor Permissions Denying all permissions by default How permissions are resolved Defining permissions with ""allow"" blocks The /-/allow-debug tool Access permissions in datasette.yaml Access to an instance Access to specific databases Access to specific tables and views Access to specific queries Controlling the ability to execute arbitrary SQL Other permissions in datasette.yaml API Tokens datasette create-token Checking permissions in plugins actor_matches_allow() Permissions debug tools Allowed resources view Permission rules view Permission check view The ds_actor cookie Including an expiry time The /-/logout page Built-in actions view-instance view-database view-database-download view-table view-query store-query update-query delete-query insert-row delete-row update-row create-table create-view alter-table set-column-type drop-table drop-view execute-sql execute-write-sql permissions-debug debug-menu Performance and caching Immutable mode Using ""datasette inspect"" HTTP caching datasette-hashed-urls CSV export URL parameters Streaming all records Binary data Binary values in JSON Linking to binary downloads Binary plugins Facets Facets in query strings Facets in configuration Suggested facets Speeding up facets with indexes Facet by JSON array Facet by date Full-text search The table page and table view API Advanced SQLite search queries Configuring full-text search for a table or view Searches using custom SQL Enabling full-text search for a SQLite table Configuring FTS using sqlite-utils Configuring FTS using csvs-to-sqlite Configuring FTS by hand FTS versions SpatiaLite Warning Installation Installing SpatiaLite on OS X Installing SpatiaLite on Linux Spatial indexing latitude/longitude columns Making use of a spatial index Importing shapefiles into SpatiaLite Importing GeoJSON polygons using Shapely Querying polygons using within() Metadata Per-database and per-table metadata Source, license and about Column descriptions Table configuration Metadata reference Top-level metadata Database-level metadata Table-level metadata Settings Using --setting Configuration directory mode Settings default_allow_sql default_page_size sql_time_limit_ms max_returned_rows max_insert_rows max_post_body_bytes num_sql_threads allow_facet default_facet_size facet_time_limit_ms facet_suggest_time_limit_ms suggest_facets allow_download allow_signed_tokens max_signed_tokens_ttl default_cache_ttl cache_size_kb allow_csv_stream max_csv_mb truncate_cells_html force_https_urls template_debug trace_debug base_url Configuring the secret Using secrets with datasette publish Introspection /-/metadata /-/versions /-/plugins /-/settings /-/config /-/databases /-/actions /-/jump /-/debug/autocomplete /-/threads /-/actor /-/messages Custom pages and templates CSS classes on the
Writing custom CSS Linking to static assets Serving files from a directory Publishing static assets Custom templates Custom pages Path parameters for pages Custom headers and status codes Returning 404s Custom redirects Custom error pages Template context Base context Database page Query page Table page Row page Plugins Installing plugins One-off plugins using --plugins-dir Deploying plugins using datasette publish Controlling which plugins are loaded Seeing what plugins are installed Plugin configuration Secret configuration values Writing plugins Tracing plugin hooks Writing one-off plugins Starting an installable plugin using cookiecutter Packaging a plugin Static assets Custom templates Writing plugins that accept configuration Designing URLs for your plugin Building URLs within plugins Plugins that define new plugin hooks JavaScript plugins The datasette_init event datasetteManager JavaScript plugin objects makeJumpSections(context) makeAboveTablePanelConfigs() makeColumnActions(columnDetails) makeColumnField(context) Selectors Plugin hooks prepare_connection(conn, database, datasette) write_wrapper(datasette, database, request, transaction) prepare_jinja2_environment(env, datasette) Page extras extra_template_vars(template, database, table, columns, view_name, request, datasette) extra_css_urls(template, database, table, columns, view_name, request, datasette) extra_js_urls(template, database, table, columns, view_name, request, datasette) extra_body_script(template, database, table, columns, view_name, request, datasette) publish_subcommand(publish) render_cell(row, value, column, table, pks, database, datasette, request, column_type) register_output_renderer(datasette) register_routes(datasette) register_commands(cli) register_facet_classes() register_actions(datasette) The resources_sql(datasette, actor) method register_column_types(datasette) asgi_wrapper(datasette) startup(datasette) actor_from_request(datasette, request) actors_from_ids(datasette, actor_ids) jinja2_environment_from_request(datasette, request, env) filters_from_request(request, database, table, datasette) permission_resources_sql(datasette, actor, action) Permission plugin examples register_magic_parameters(datasette) forbidden(datasette, request, message) handle_exception(datasette, request, exception) menu_links(datasette, actor, request) jump_items_sql(datasette, actor, request) Action hooks table_actions(datasette, actor, database, table, request) view_actions(datasette, actor, database, view, request) query_actions(datasette, actor, database, query_name, request, sql, params) row_actions(datasette, actor, request, database, table, row) database_actions(datasette, actor, database, request) homepage_actions(datasette, actor, request) Template slots top_homepage(datasette, request) top_database(datasette, request, database) top_table(datasette, request, database, table) top_row(datasette, request, database, table, row) top_query(datasette, request, database, sql) top_stored_query(datasette, request, database, query_name) Event tracking track_event(datasette, event) register_events(datasette) register_token_handler(datasette) Testing plugins Setting up a Datasette test instance Using Datasette's fixtures database Automatic cleanup of Datasette instances Using datasette.client in tests Using pdb for errors thrown inside Datasette Using pytest fixtures Testing outbound HTTP calls with pytest-httpx Registering a plugin for the duration of a test Internals for plugins Request object The MultiParams class The FormData class The UploadedFile class Response class Returning a response with .asgi_send(send) Setting cookies with response.set_cookie() Datasette class .databases .actions .plugin_config(plugin_name, database=None, table=None) await .render_template(template, context=None, request=None) .static(path, plugin=None, mount=None) await .actors_from_ids(actor_ids) await .allowed(*, action, resource, actor=None) await .allowed_many(*, actions, resource, actor=None) await .allowed_resources(action, actor=None, *, parent=None, include_is_private=False, include_reasons=False, limit=100, next=None) await .allowed_resources_sql(*, action, actor=None, parent=None, include_is_private=False) await .ensure_permission(action, resource=None, actor=None) await .check_visibility(actor, action, resource=None) await .create_token(actor_id, expires_after=None, restrictions=None, handler=None) await .verify_token(token) .get_database(name) .get_internal_database() Getting and setting metadata Stored queries Column types .add_database(db, name=None, route=None) .add_memory_database(memory_name, name=None, route=None) .remove_database(name) .close() await .track_event(event) .sign(value, namespace=""default"") .unsign(value, namespace=""default"") .add_message(request, message, type=datasette.INFO) .absolute_url(request, path) .setting(key) .resolve_database(request) .resolve_table(request) .resolve_row(request) datasette.client datasette.urls Permission classes and utilities PermissionSQL class Database class Database(ds, path=None, is_mutable=True, is_memory=False, memory_name=None, is_temp_disk=False) db.hash await db.execute(sql, ...) Results await db.execute_fn(fn) await db.execute_write(sql, params=None, block=True, request=None, return_all=False, returning_limit=10, transaction=True, time_limit_ms=2000) await db.execute_write_script(sql, block=True) await db.execute_write_many(sql, params_seq, block=True) await db.execute_write_fn(fn, block=True, transaction=True) await db.execute_isolated_fn(fn) db.close() Database introspection CSRF protection Datasette's internal database Internal database schema The datasette.utils module parse_metadata(content) await_me_maybe(value) named_parameters(sql) Tilde encoding call_with_supported_arguments(fn, **kwargs) await async_call_with_supported_arguments(fn, **kwargs) JSON encoding datasette.tracer Tracing child tasks Import shortcuts Events LoginEvent LogoutEvent CreateTokenEvent CreateTableEvent DropTableEvent AlterTableEvent InsertRowsEvent UpsertRowsEvent UpdateRowEvent RenameTableEvent DeleteRowEvent Upgrade guide Datasette 0.X -> 1.0 New URL for SQL queries Metadata changes Datasette 1.0a20 plugin upgrade guide Permissions are now actions permission_allowed() hook is replaced by permission_resources_sql() Using datasette.allowed() to check permissions instead of datasette.permission_allowed() Root user checks are no longer necessary Target the new APIs exclusively Fixing async with httpx.AsyncClient(app=app) Migrating from metadata= to config= Datasette 1.0a25: create_token() signature change CSRF protection is now header-based Contributing General guidelines Setting up a development environment Running the tests Running Playwright tests Using fixtures Debugging Code formatting Running Black blacken-docs Prettier Editing and building the documentation Running Cog Documented template contexts Continuously deployed demo instances Release process Alpha and beta releases Releasing bug fixes from a branch Upgrading CodeMirror Changelog 1.0a39 (2026-09-10) Other improvements and fixes 1.0a38 (2026-08-06) 1.0a37 (2026-07-14) 1.0a36 (2026-07-07) JSON API: breaking changes JSON API: other improvements 1.0a35 (2026-06-23) 1.0a34 (2026-06-16) 1.0a33 (2026-06-11) Editing and deleting stored queries ?_extra= support for row and query pages Security fixes Bug fixes 1.0a32 (2026-05-31) 1.0a31 (2026-05-28) Write SQL UI Stored queries Plugin API changes Bug fixes 1.0a30 (2026-05-24) 1.0a29 (2026-05-12) 1.0a28 (2026-04-16) 1.0a27 (2026-04-15) CSRF protection no longer uses CSRF tokens RenameTableEvent when a table is renamed Other changes 1.0a26 (2026-03-18) New column_types system UI for selecting columns and their order Other changes 1.0a25 (2026-02-25) write_wrapper() plugin hook for intercepting write operations register_token_handler() plugin hook for custom API token backends render_cell() now receives a pks parameter Other changes 1.0a24 (2026-01-29) request.form() method for POST data and file uploads render_cell and foreign_key_tables extras for the JSON API uv run pytest with a dev= dependency group Other changes 1.0a23 (2025-12-02) 1.0a22 (2025-11-13) 1.0a21 (2025-11-05) 0.65.2 (2025-11-05) 1.0a20 (2025-11-03) Permission system redesign Other changes 1.0a19 (2025-04-21) 1.0a18 (2025-04-16) 1.0a17 (2025-02-06) 0.65.1 (2024-11-28) 0.65 (2024-10-07) 1.0a16 (2024-09-05) 1.0a15 (2024-08-15) 1.0a14 (2024-08-05) 0.64.8 (2024-06-21) 0.64.7 (2024-06-12) 1.0a13 (2024-03-12) 1.0a12 (2024-02-29) 1.0a11 (2024-02-19) 1.0a10 (2024-02-17) 1.0a9 (2024-02-16) Alter table support for create, insert, upsert and update Permissions fix for the upsert API Permission checks now consider opinions from every plugin Other changes 1.0a8 (2024-02-07) Configuration JavaScript plugins Plugin hooks Documentation Minor fixes 0.64.6 (2023-12-22) 0.64.5 (2023-10-08) 1.0a7 (2023-09-21) 0.64.4 (2023-09-21) 1.0a6 (2023-09-07) 1.0a5 (2023-08-29) 1.0a4 (2023-08-21) 1.0a3 (2023-08-09) Smaller changes 0.64.2 (2023-03-08) 0.64.1 (2023-01-11) 0.64 (2023-01-09) 0.63.3 (2022-12-17) 1.0a2 (2022-12-14) 1.0a1 (2022-12-01) 1.0a0 (2022-11-29) Signed API tokens Write API 0.63.2 (2022-11-18) 0.63.1 (2022-11-10) 0.63 (2022-10-27) Features Plugin hooks and internals Documentation 0.62 (2022-08-14) Features Plugin hooks Bug fixes Documentation 0.61.1 (2022-03-23) 0.61 (2022-03-23) 0.60.2 (2022-02-07) 0.60.1 (2022-01-20) 0.60 (2022-01-13) Plugins and internals Faceting Other small fixes 0.59.4 (2021-11-29) 0.59.3 (2021-11-20) 0.59.2 (2021-11-13) 0.59.1 (2021-10-24) 0.59 (2021-10-14) 0.58.1 (2021-07-16) 0.58 (2021-07-14) 0.57.1 (2021-06-08) 0.57 (2021-06-05) New features Bug fixes and other improvements 0.56.1 (2021-06-05) 0.56 (2021-03-28) 0.55 (2021-02-18) 0.54.1 (2021-02-02) 0.54 (2021-01-25) The _internal database Named in-memory database support JavaScript modules Code formatting with Black and Prettier Other changes 0.53 (2020-12-10) 0.52.5 (2020-12-09) 0.52.4 (2020-12-05) 0.52.3 (2020-12-03) 0.52.2 (2020-12-02) 0.52.1 (2020-11-29) 0.52 (2020-11-28) 0.51.1 (2020-10-31) 0.51 (2020-10-31) New visual design Plugins can now add links within Datasette Binary data URL building Running Datasette behind a proxy Smaller changes 0.50.2 (2020-10-09) 0.50.1 (2020-10-09) 0.50 (2020-10-09) 0.49.1 (2020-09-15) 0.49 (2020-09-14) 0.48 (2020-08-16) 0.47.3 (2020-08-15) 0.47.2 (2020-08-12) 0.47.1 (2020-08-11) 0.47 (2020-08-11) 0.46 (2020-08-09) 0.45 (2020-07-01) Magic parameters for canned queries Log out Better plugin documentation New plugin hooks Smaller changes 0.44 (2020-06-11) Authentication Permissions Writable canned queries Flash messages Signed values and secrets CSRF protection Cookie methods register_routes() plugin hooks Smaller changes The road to Datasette 1.0 0.43 (2020-05-28) 0.42 (2020-05-08) 0.41 (2020-05-06) 0.40 (2020-04-21) 0.39 (2020-03-24) 0.38 (2020-03-08) 0.37.1 (2020-03-02) 0.37 (2020-02-25) 0.36 (2020-02-21) 0.35 (2020-02-04) 0.34 (2020-01-29) 0.33 (2019-12-22) 0.32 (2019-11-14) 0.31.2 (2019-11-13) 0.31.1 (2019-11-12) 0.31 (2019-11-11) 0.30.2 (2019-11-02) 0.30.1 (2019-10-30) 0.30 (2019-10-18) 0.29.3 (2019-09-02) 0.29.2 (2019-07-13) 0.29.1 (2019-07-11) 0.29 (2019-07-07) ASGI New plugin hook: asgi_wrapper New plugin hook: extra_template_vars Secret plugin configuration options Facet by date Easier custom templates for table rows ?_through= for joins through many-to-many tables Small changes 0.28 (2019-05-19) Supporting databases that change Faceting improvements, and faceting plugins datasette publish cloudrun register_output_renderer plugins Medium changes Small changes 0.27.1 (2019-05-09) 0.27 (2019-01-31) 0.26.1 (2019-01-10) 0.26 (2019-01-02) 0.25.2 (2018-12-16) 0.25.1 (2018-11-04) 0.25 (2018-09-19) 0.24 (2018-07-23) 0.23.2 (2018-07-07) 0.23.1 (2018-06-21) 0.23 (2018-06-18) CSV export Foreign key expansions New configuration settings Control HTTP caching with ?_ttl= Improved support for SpatiaLite latest.datasette.io Miscellaneous 0.22.1 (2018-05-23) 0.22 (2018-05-20) 0.21 (2018-05-05) 0.20 (2018-04-20) 0.19 (2018-04-16) 0.18 (2018-04-14) 0.17 (2018-04-13) 0.16 (2018-04-13) 0.15 (2018-04-09) 0.14 (2017-12-09) 0.13 (2017-11-24) 0.12 (2017-11-16) 0.11 (2017-11-14) 0.10 (2017-11-14) 0.9 (2017-11-13) 0.8 (2017-11-13)",508, 780,Datasette,"An open source multi-tool for exploring and publishing data Datasette is a tool for exploring and publishing data. It helps people take data of any shape or size and publish that as an interactive, explorable website and accompanying API. Datasette is aimed at data journalists, museum curators, archivists, local governments and anyone else who has data that they wish to share with the world. It is part of a wider ecosystem of tools and plugins dedicated to making working with structured data as productive as possible. Explore a demo , watch a presentation about the project . Interested in learning Datasette? Start with the official tutorials . Support questions, feedback? Join the Datasette Discord .",508, 779,Selectors,"These are available on the selectors property of the datasetteManager object. const DOM_SELECTORS = { /** Should have one match */ jsonExportLink: "".export-links a[href*=json]"", /** Event listeners that go outside of the main table, e.g. existing scroll listener */ tableWrapper: "".table-wrapper"", table: ""table.rows-and-columns"", aboveTablePanel: "".above-table-panel"", // These could have multiple matches /** Used for selecting table headers. Use makeColumnActions if you want to add menu items. */ tableHeaders: `table.rows-and-columns th`, /** Used to add ""where"" clauses to query using direct manipulation */ filterRows: "".filter-row"", /** Used to show top available enum values for a column (""facets"") */ facetResults: "".facet-results [data-column]"", };",508, 778,Accessibility,"Custom fields are responsible for preserving the accessibility of the form: The visible field label should name the control. Use field.labelId with aria-labelledby when wrapping or replacing the visible input. Field metadata should remain available to assistive technology. Use field.descriptionId with aria-describedby . Keyboard users must be able to operate every part of the custom field. If the field opens an inline picker or other nested UI, Escape should close that nested UI first and return focus to a sensible element. If a control performs asynchronous loading, expose loading and error states in the UI. Use appropriate ARIA live regions where the state change is important to understand the field. If a plugin hides field.input , the replacement UI must still make the current value and available actions clear. Plugins should not submit the row themselves from inside makeColumnField() controls. Datasette owns the insert/edit dialog lifecycle, form submission, API call, error handling and row refresh.",508, 777,Example: textarea-backed custom element,"This example handles a markdown-editor column type by asking Datasette for a textarea and wrapping that textarea in a custom