1.0a36
Pre-release
Pre-release
The signature features of this alpha are new UIs for inserting multiple rows at once (from TSV, CSV or JSON) and for creating a table from rows, plus a large number of small JSON API consistency fixes in preparation for a 1.0 stable release.
- Table pages now offer an "Insert multiple rows" mode in the row insertion dialog. This accepts pasted TSV, CSV or JSON, previews the parsed rows before inserting them, validates unknown columns as data is pasted and displays omitted auto integer primary keys as
autoin the preview. (#2813) - The bulk insert UI can skip rows with existing primary keys, or update existing rows and insert new rows using the existing
/<database>/<table>/-/upsertAPI when the actor has both insert-row and update-row permissions. (#2813) - The "Create table" dialog now includes a "Create table from data" mode. Paste TSV, CSV or JSON rows to preview inferred columns and types, choose the table name and primary key, then create the table and insert those rows in one step. (#2813)
- Datasette's JSON APIs now consistently encode every
BLOBvalue using the documented binary value JSON format, even when the bytes could be decoded as UTF-8 text. (#2806, #2822) - The insert and edit row dialogs now provide a dedicated control for
BLOBvalues. Existing binary values are shown by byte size, image values under 10MB are previewed as thumbnails, and replacements can be attached, dropped or pasted into the control. (#2806, #2822) - The table and row JSON APIs now support
?_extra=column_detailsfor returning SQLite schema details for columns, including declared type, SQLite affinity, primary key,NOT NULL, default and hidden-column metadata. - POST bodies that Datasette reads fully into memory - such as JSON submitted to the write API - are now capped by the new max_post_body_bytes setting, defaulting to 2MB. Oversized requests are rejected with an HTTP 413 error as soon as the limit is exceeded, protecting smaller servers from memory exhaustion. File uploads are unaffected -
request.form()streams those to disk and has its own separate limits. (#2823) - Row pages for tables with compound primary keys now return a
400error instead of a500error when the URL row identifier does not contain the correct number of primary key values. Thanks, Zain Dana Harper. (#2811, #2815) - The execute-write-sql interface now supports
CREATE VIEWandDROP VIEWstatements, gated by the new create-view and drop-view permissions. (#2819, #2818) - Saved-query SQL analysis now handles recursive CTEs, fixing a bug where storing a valid read-only recursive query could be disabled by SQLite's internal
SQLITE_RECURSIVEauthorizer callback. (#2809, #2812) named_parameters()now correctly ignores SQLite comment markers that appear inside string literals, so query forms no longer drop later:namedparameters from SQL such asselect '--' || :name. Thanks, JSap0914. (#2783)- Datasette's internal database schema is now managed using sqlite-utils migrations, using the new dependency on
sqlite-utils>=4.0. (#2827) datasette.utils.CustomJSONEncoderis now documented as a public API for plugins that need to serialize Datasette values to JSON. Thanks, Chris Amico. (#1983, #1996)
This release also includes the results of a detailed consistency review of Datasette's JSON API in preparation for the 1.0 stable release. Several of these changes are backwards-incompatible with previous 1.0 alphas. The new API stability documentation describes exactly which parts of the JSON API are covered by the 1.0 stability promise.
JSON API: breaking changes
- JSON error responses now use a single canonical format across every endpoint:
{"ok": false, "error": "...", "errors": [...], "status": 400}. Theerrorkey joins all error messages together,errorsis the full list of messages andstatusalways matches the HTTP status code. The legacytitlekey is no longer included in JSON errors (it remains available to the HTML error template), and endpoints that previously returned bare{"error": ...}objects have been updated. See Error responses. - Every JSON object success response now includes
"ok": true, including introspection endpoints such as/-/versionsand/-/settings. /-/plugins.json,/-/databases.jsonand/-/actions.jsonnow return objects -{"ok": true, "plugins": [...]}and equivalents - instead of top-level JSON arrays, so these responses can gain additional keys in the future without a breaking change. Thedatasette pluginsCLI command still outputs a plain array./-/databasesnow only lists databases the current actor is allowed to view. It previously listed every attached database, including their filesystem paths, to any actor withview-instance.- Requests with an invalid or expired
Authorization: Bearertoken now receive a401status with the standard error body and aWWW-Authenticate: Bearer error="invalid_token"header, instead of being silently treated as unauthenticated. Bearer tokens that no registered token handler recognizes are still ignored, so authentication plugins with their own token formats keep working. Plugin token handlers can raise the newdatasette.TokenInvalidexception to trigger the same behavior. - Permission errors for JSON requests now return the standard JSON error format with a
403status. The default forbidden handling previously rendered an HTML error page even for.jsonrequests. POSTto a write canned query now returns a400error when the SQL fails to execute, instead of a200status with"ok": falsein the body. The error response includes the standard error keys plus a"redirect"key.- The row update API with
"return": truenow responds with a"rows"list, matching insert and upsert, instead of a singular"row"object. - Row delete write failures - such as a constraint violation raised by a trigger - now return
400instead of500, matching the other write endpoints. /<database>/-/query.jsonwith a missing or blank?sql=parameter now returns a400error, as the CSV format already did, instead of a200with empty rows.- Unknown
?_extra=names now return a400error for JSON and other data formats, instead of being silently ignored. HTML pages continue to ignore unknown names. - Table JSON responses now include
next_urlalongsidenextby default - both arenullon the final page. The now-redundant?_extra=next_urlparameter has been removed. - The stored query list JSON no longer includes
has_more-"next": nullis the end-of-results signal across the whole API. This change also uncovered and fixed a bug where the query listnext_urlpointed at the HTML page and was a relative path; it is now an absolute URL that preserves the requested format. - Stored query JSON objects no longer duplicate the list of parameter names as both
paramsandparameters- onlyparametersremains. The query create and update APIs no longer acceptparamsas an input alias either;paramsis still the documented key for queries defined in configuration. - Page size parameters are now consistent across the API: the stored query lists accept
?_size=maxand return a400error for values over the maximum instead of silently clamping them, and the/-/allowedand/-/rulespermission debug endpoints renamed theirpageandpage_sizeparameters to_pageand_size, matching the underscore grammar used by every other Datasette system parameter. /-/threadsnow requires thepermissions-debugpermission, since it exposes runtime internals such as file paths. It previously only requiredview-instance.- Trusted stored queries - those defined in configuration - can no longer be deleted through the JSON API or web interface, matching the existing restriction on editing them.
- The
/<database>/-/schemaendpoints now check theview-databasepermission before checking whether the database exists, so unauthorized actors can no longer probe for the existence of databases. - SQL time limit errors in JSON responses are now a plain text message. The error string previously embedded an HTML fragment.
- The undocumented homepage JSON at
/.jsonnow returnsdatabasesas a list of objects rather than an object keyed by database name, matching every other collection in the API. - The legacy
.jsonoformat extension, long since superseded by?_shape=, has been removed.
JSON API: other improvements
- The write API endpoints now parse the request body as JSON regardless of the
Content-Typeheader, socurl -dinvocations work without remembering to set it. Invalid JSON is a400error. Cross-site request forgery remains prevented by Datasette'sOriginandSec-Fetch-Sitechecks. This also fixes a500error from the insert API when theContent-Typeheader was missing entirely. - New
Response.error(messages, status=400)helper for plugins that need to return a JSON error in Datasette's standard format. See Response class. - New
count_truncatedextra for table JSON, included automatically whenevercountis requested.truemeans the count reached Datasette's counting limit and the real number of rows may be higher. See Expanding JSON responses. - JSON endpoints that are not part of the documented stable API now declare themselves with an
"unstable"key in their responses. - New documentation covering the grammar for boolean query string arguments, the reason upsert returns
200where insert returns201, and advice for plugin authors on naming secret configuration keys so that/-/configredacts them automatically.