{"authentication~3Aallowdebugview": {"id": "authentication:allowdebugview", "page": "authentication", "ref": "allowdebugview", "title": "The /-/allow-debug tool", "content": "The  /-/allow-debug  tool lets you try out different   \"action\"  blocks against different  \"actor\"  JSON objects. You can try that out here:  https://latest.datasette.io/-/allow-debug", "breadcrumbs": "[\"Authentication and permissions\", \"Permissions\"]", "references": "[{\"href\": \"https://latest.datasette.io/-/allow-debug\", \"label\": \"https://latest.datasette.io/-/allow-debug\"}]"}, "authentication~3Aauthentication": {"id": "authentication:authentication", "page": "authentication", "ref": "authentication", "title": "Authentication and permissions", "content": "Datasette does not require authentication by default. Any visitor to a Datasette instance can explore the full data and execute read-only SQL queries. \n         Datasette's plugin system can be used to add many different styles of authentication, such as user accounts, single sign-on or API keys.", "breadcrumbs": "[]", "references": "[]"}, "authentication~3Aauthentication-actor": {"id": "authentication:authentication-actor", "page": "authentication", "ref": "authentication-actor", "title": "Actors", "content": "Through plugins, Datasette can support both authenticated users (with cookies) and authenticated API agents (via authentication tokens). The word \"actor\" is used to cover both of these cases. \n             Every request to Datasette has an associated actor value, available in the code as  request.actor . This can be  None  for unauthenticated requests, or a JSON compatible Python dictionary for authenticated users or API agents. \n             The actor dictionary can be any shape - the design of that data structure is left up to the plugins. A useful convention is to include an  \"id\"  string, as demonstrated by the \"root\" actor below. \n             Plugins can use the  actor_from_request(datasette, request)  hook to implement custom logic for authenticating an actor based on the incoming HTTP request.", "breadcrumbs": "[\"Authentication and permissions\"]", "references": "[]"}, "authentication~3Aauthentication-actor-matches-allow": {"id": "authentication:authentication-actor-matches-allow", "page": "authentication", "ref": "authentication-actor-matches-allow", "title": "actor_matches_allow()", "content": "Plugins that wish to implement this same  \"allow\"  block permissions scheme can take advantage of the  datasette.utils.actor_matches_allow(actor, allow)  function: \n             from datasette.utils import actor_matches_allow\n\nactor_matches_allow({\"id\": \"root\"}, {\"id\": \"*\"})\n# returns True \n             The currently authenticated actor is made available to plugins as  request.actor .", "breadcrumbs": "[\"Authentication and permissions\"]", "references": "[]"}, "authentication~3Aauthentication-ds-actor": {"id": "authentication:authentication-ds-actor", "page": "authentication", "ref": "authentication-ds-actor", "title": "The ds_actor cookie", "content": "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. \n             Authentication plugins can set signed  ds_actor  cookies themselves like so: \n             response = Response.redirect(\"/\")\nresponse.set_cookie(\n    \"ds_actor\",\n    datasette.sign({\"a\": {\"id\": \"cleopaws\"}}, \"actor\"),\n) \n             Note that you need to pass  \"actor\"  as the namespace to  .sign(value, namespace=\"default\") . \n             The shape of data encoded in the cookie is as follows: \n             {\n    \"a\": {... actor ...}\n}", "breadcrumbs": "[\"Authentication and permissions\"]", "references": "[]"}, "authentication~3Aauthentication-ds-actor-expiry": {"id": "authentication:authentication-ds-actor-expiry", "page": "authentication", "ref": "authentication-ds-actor-expiry", "title": "Including an expiry time", "content": "ds_actor  cookies can optionally include a signed expiry timestamp, after which the cookies will no longer be valid. Authentication plugins may chose to use this mechanism to limit the lifetime of the cookie. For example, if a plugin implements single-sign-on against another source it may decide to set short-lived cookies so that if the user is removed from the SSO system their existing Datasette cookies will stop working shortly afterwards. \n                 To include an expiry, add a  \"e\"  key to the cookie value containing a base62-encoded integer representing the timestamp when the cookie should expire. For example, here's how to set a cookie that expires after 24 hours: \n                 import time\nfrom datasette.utils import baseconv\n\nexpires_at = int(time.time()) + (24 * 60 * 60)\n\nresponse = Response.redirect(\"/\")\nresponse.set_cookie(\n    \"ds_actor\",\n    datasette.sign(\n        {\n            \"a\": {\"id\": \"cleopaws\"},\n            \"e\": baseconv.base62.encode(expires_at),\n        },\n        \"actor\",\n    ),\n) \n                 The resulting cookie will encode data that looks something like this: \n                 {\n    \"a\": {\n        \"id\": \"cleopaws\"\n    },\n    \"e\": \"1jjSji\"\n}", "breadcrumbs": "[\"Authentication and permissions\", \"The ds_actor cookie\"]", "references": "[]"}, "authentication~3Aauthentication-permissions": {"id": "authentication:authentication-permissions", "page": "authentication", "ref": "authentication-permissions", "title": "Permissions", "content": "Datasette has an extensive permissions system built-in, which can be further extended and customized by plugins. \n             The key question the permissions system answers is this: \n             \n                 Is this  actor  allowed to perform this  action , optionally against this particular  resource ? \n             \n             Actors  are  described above . \n             An  action  is a string describing the action the actor would like to perform. A full list is  provided below  - examples include  view-table  and  execute-sql . \n             A  resource  is the item the actor wishes to interact with - for example a specific database or table. Some actions, such as  permissions-debug , are not associated with a particular resource. \n             Datasette's built-in view permissions ( view-database ,  view-table  etc) default to  allow  - unless you  configure additional permission rules  unauthenticated users will be allowed to access content. \n             Permissions with potentially harmful effects should default to  deny . Plugin authors should account for this when designing new plugins - for example, the  datasette-upload-csvs  plugin defaults to deny so that installations don't accidentally allow unauthenticated users to create new tables by uploading a CSV file.", "breadcrumbs": "[\"Authentication and permissions\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette-upload-csvs\", \"label\": \"datasette-upload-csvs\"}]"}, "authentication~3Aauthentication-permissions-allow": {"id": "authentication:authentication-permissions-allow", "page": "authentication", "ref": "authentication-permissions-allow", "title": "Defining permissions with \"allow\" blocks", "content": "The standard way to define permissions in Datasette is to use an  \"allow\"  block. This is a JSON document describing which actors are allowed to perform a permission. \n                 The most basic form of allow block is this ( allow demo ,  deny demo ): \n                 {\n    \"allow\": {\n        \"id\": \"root\"\n    }\n} \n                 This will match any actors with an  \"id\"  property of  \"root\"  - for example, an actor that looks like this: \n                 {\n    \"id\": \"root\",\n    \"name\": \"Root User\"\n} \n                 An allow block can specify \"deny all\" using  false  ( demo ): \n                 {\n    \"allow\": false\n} \n                 An  \"allow\"  of  true  allows all access ( demo ): \n                 {\n    \"allow\": true\n} \n                 Allow keys can provide a list of values. These will match any actor that has any of those values ( allow demo ,  deny demo ): \n                 {\n    \"allow\": {\n        \"id\": [\"simon\", \"cleopaws\"]\n    }\n} \n                 This will match any actor with an  \"id\"  of either  \"simon\"  or  \"cleopaws\" . \n                 Actors can have properties that feature a list of values. These will be matched against the list of values in an allow block. Consider the following actor: \n                 {\n    \"id\": \"simon\",\n    \"roles\": [\"staff\", \"developer\"]\n} \n                 This allow block will provide access to any actor that has  \"developer\"  as one of their roles ( allow demo ,  deny demo ): \n                 {\n    \"allow\": {\n        \"roles\": [\"developer\"]\n    }\n} \n                 Note that \"roles\" is not a concept that is baked into Datasette - it's a convention that plugins can choose to implement and act on. \n                 If you want to provide access to any actor with a value for a specific key, use  \"*\" . For example, to match any logged-in user specify the following ( allow demo ,  deny demo ): \n                 {\n    \"allow\": {\n        \"id\": \"*\"\n    }\n} \n                 You can specify that only unauthenticated actors (from anonymous HTTP requests) should be allowed access using the special  \"unauthenticated\": true  key in an allow block ( allow demo ,  deny demo ): \n                 {\n    \"allow\": {\n        \"unauthenticated\": true\n    }\n} \n                 Allow keys act as an \"or\" mechanism. An actor will be able to execute the query if any of their JSON properties match any of the values in the corresponding lists in the  allow  block. The following block will allow users with either a  role  of  \"ops\"  OR users who have an  id  of  \"simon\"  or  \"cleopaws\" : \n                 {\n    \"allow\": {\n        \"id\": [\"simon\", \"cleopaws\"],\n        \"role\": \"ops\"\n    }\n} \n                 Demo for cleopaws ,  demo for ops role ,  demo for an actor matching neither rule .", "breadcrumbs": "[\"Authentication and permissions\", \"Permissions\"]", "references": "[{\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%22id%22%3A+%22root%22%7D&allow=%7B%0D%0A++++++++%22id%22%3A+%22root%22%0D%0A++++%7D\", \"label\": \"allow demo\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%22id%22%3A+%22trevor%22%7D&allow=%7B%0D%0A++++++++%22id%22%3A+%22root%22%0D%0A++++%7D\", \"label\": \"deny demo\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%0D%0A++++%22id%22%3A+%22root%22%0D%0A%7D&allow=false\", \"label\": \"demo\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%0D%0A++++%22id%22%3A+%22root%22%0D%0A%7D&allow=true\", \"label\": \"demo\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%0D%0A++++%22id%22%3A+%22cleopaws%22%0D%0A%7D&allow=%7B%0D%0A++++%22id%22%3A+%5B%0D%0A++++++++%22simon%22%2C%0D%0A++++++++%22cleopaws%22%0D%0A++++%5D%0D%0A%7D\", \"label\": \"allow demo\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%0D%0A++++%22id%22%3A+%22pancakes%22%0D%0A%7D&allow=%7B%0D%0A++++%22id%22%3A+%5B%0D%0A++++++++%22simon%22%2C%0D%0A++++++++%22cleopaws%22%0D%0A++++%5D%0D%0A%7D\", \"label\": \"deny demo\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%0D%0A++++%22id%22%3A+%22simon%22%2C%0D%0A++++%22roles%22%3A+%5B%0D%0A++++++++%22staff%22%2C%0D%0A++++++++%22developer%22%0D%0A++++%5D%0D%0A%7D&allow=%7B%0D%0A++++%22roles%22%3A+%5B%0D%0A++++++++%22developer%22%0D%0A++++%5D%0D%0A%7D\", \"label\": \"allow demo\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%0D%0A++++%22id%22%3A+%22cleopaws%22%2C%0D%0A++++%22roles%22%3A+%5B%22dog%22%5D%0D%0A%7D&allow=%7B%0D%0A++++%22roles%22%3A+%5B%0D%0A++++++++%22developer%22%0D%0A++++%5D%0D%0A%7D\", \"label\": \"deny demo\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%0D%0A++++%22id%22%3A+%22simon%22%0D%0A%7D&allow=%7B%0D%0A++++%22id%22%3A+%22*%22%0D%0A%7D\", \"label\": \"allow demo\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%0D%0A++++%22bot%22%3A+%22readme-bot%22%0D%0A%7D&allow=%7B%0D%0A++++%22id%22%3A+%22*%22%0D%0A%7D\", \"label\": \"deny demo\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=null&allow=%7B%0D%0A++++%22unauthenticated%22%3A+true%0D%0A%7D\", \"label\": \"allow demo\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%0D%0A++++%22id%22%3A+%22hello%22%0D%0A%7D&allow=%7B%0D%0A++++%22unauthenticated%22%3A+true%0D%0A%7D\", \"label\": \"deny demo\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%0D%0A++++%22id%22%3A+%22cleopaws%22%0D%0A%7D&allow=%7B%0D%0A++++%22id%22%3A+%5B%0D%0A++++++++%22simon%22%2C%0D%0A++++++++%22cleopaws%22%0D%0A++++%5D%2C%0D%0A++++%22role%22%3A+%22ops%22%0D%0A%7D\", \"label\": \"Demo for cleopaws\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%0D%0A++++%22id%22%3A+%22trevor%22%2C%0D%0A++++%22role%22%3A+%5B%0D%0A++++++++%22ops%22%2C%0D%0A++++++++%22staff%22%0D%0A++++%5D%0D%0A%7D&allow=%7B%0D%0A++++%22id%22%3A+%5B%0D%0A++++++++%22simon%22%2C%0D%0A++++++++%22cleopaws%22%0D%0A++++%5D%2C%0D%0A++++%22role%22%3A+%22ops%22%0D%0A%7D\", \"label\": \"demo for ops role\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%0D%0A++++%22id%22%3A+%22percy%22%2C%0D%0A++++%22role%22%3A+%5B%0D%0A++++++++%22staff%22%0D%0A++++%5D%0D%0A%7D&allow=%7B%0D%0A++++%22id%22%3A+%5B%0D%0A++++++++%22simon%22%2C%0D%0A++++++++%22cleopaws%22%0D%0A++++%5D%2C%0D%0A++++%22role%22%3A+%22ops%22%0D%0A%7D\", \"label\": \"demo for an actor matching neither rule\"}]"}, "authentication~3Aauthentication-permissions-database": {"id": "authentication:authentication-permissions-database", "page": "authentication", "ref": "authentication-permissions-database", "title": "Controlling access to specific databases", "content": "To limit access to a specific  private.db  database to just authenticated users, use the  \"allow\"  block like this: \n                 {\n    \"databases\": {\n        \"private\": {\n            \"allow\": {\n                \"id\": \"*\"\n            }\n        }\n    }\n}", "breadcrumbs": "[\"Authentication and permissions\", \"Configuring permissions in metadata.json\"]", "references": "[]"}, "authentication~3Aauthentication-permissions-execute-sql": {"id": "authentication:authentication-permissions-execute-sql", "page": "authentication", "ref": "authentication-permissions-execute-sql", "title": "Controlling the ability to execute arbitrary SQL", "content": "Datasette defaults to allowing any site visitor to execute their own custom SQL queries, for example using the form on  the database page  or by appending a  ?_where=  parameter to the table page  like this . \n                 Access to this ability is controlled by the  execute-sql  permission. \n                 The easiest way to disable arbitrary SQL queries is using the  default_allow_sql setting  when you first start Datasette running. \n                 You can alternatively use an  \"allow_sql\"  block to control who is allowed to execute arbitrary SQL queries. \n                 To prevent any user from executing arbitrary SQL queries, use this: \n                 {\n    \"allow_sql\": false\n} \n                 To enable just the  root user  to execute SQL for all databases in your instance, use the following: \n                 {\n    \"allow_sql\": {\n        \"id\": \"root\"\n    }\n} \n                 To limit this ability for just one specific database, use this: \n                 {\n    \"databases\": {\n        \"mydatabase\": {\n            \"allow_sql\": {\n                \"id\": \"root\"\n            }\n        }\n    }\n}", "breadcrumbs": "[\"Authentication and permissions\", \"Configuring permissions in metadata.json\"]", "references": "[{\"href\": \"https://latest.datasette.io/fixtures\", \"label\": \"the database page\"}, {\"href\": \"https://latest.datasette.io/fixtures/facetable?_where=_city_id=1\", \"label\": \"like this\"}]"}, "authentication~3Aauthentication-permissions-instance": {"id": "authentication:authentication-permissions-instance", "page": "authentication", "ref": "authentication-permissions-instance", "title": "Controlling access to an instance", "content": "Here's how to restrict access to your entire Datasette instance to just the  \"id\": \"root\"  user: \n                 {\n    \"title\": \"My private Datasette instance\",\n    \"allow\": {\n        \"id\": \"root\"\n    }\n} \n                 To deny access to all users, you can use  \"allow\": false : \n                 {\n    \"title\": \"My entirely inaccessible instance\",\n    \"allow\": false\n} \n                 One reason to do this is if you are using a Datasette plugin - such as  datasette-permissions-sql  - to control permissions instead.", "breadcrumbs": "[\"Authentication and permissions\", \"Configuring permissions in metadata.json\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette-permissions-sql\", \"label\": \"datasette-permissions-sql\"}]"}, "authentication~3Aauthentication-permissions-metadata": {"id": "authentication:authentication-permissions-metadata", "page": "authentication", "ref": "authentication-permissions-metadata", "title": "Configuring permissions in metadata.json", "content": "You can limit who is allowed to view different parts of your Datasette instance using  \"allow\"  keys in your  Metadata  configuration. \n             You can control the following: \n             \n                 \n                     Access to the entire Datasette instance \n                 \n                 \n                     Access to specific databases \n                 \n                 \n                     Access to specific tables and views \n                 \n                 \n                     Access to specific  Canned queries \n                 \n             \n             If a user cannot access a specific database, they will not be able to access tables, views or queries within that database. If a user cannot access the instance they will not be able to access any of the databases, tables, views or queries.", "breadcrumbs": "[\"Authentication and permissions\"]", "references": "[]"}, "authentication~3Aauthentication-permissions-query": {"id": "authentication:authentication-permissions-query", "page": "authentication", "ref": "authentication-permissions-query", "title": "Controlling access to specific canned queries", "content": "Canned queries  allow you to configure named SQL queries in your  metadata.json  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. \n                 To limit access to the  add_name  canned query in your  dogs.db  database to just the  root user : \n                 {\n    \"databases\": {\n        \"dogs\": {\n            \"queries\": {\n                \"add_name\": {\n                    \"sql\": \"INSERT INTO names (name) VALUES (:name)\",\n                    \"write\": true,\n                    \"allow\": {\n                        \"id\": [\"root\"]\n                    }\n                }\n            }\n        }\n    }\n}", "breadcrumbs": "[\"Authentication and permissions\", \"Configuring permissions in metadata.json\"]", "references": "[]"}, "authentication~3Aauthentication-permissions-table": {"id": "authentication:authentication-permissions-table", "page": "authentication", "ref": "authentication-permissions-table", "title": "Controlling access to specific tables and views", "content": "To limit access to the  users  table in your  bakery.db  database: \n                 {\n    \"databases\": {\n        \"bakery\": {\n            \"tables\": {\n                \"users\": {\n                    \"allow\": {\n                        \"id\": \"*\"\n                    }\n                }\n            }\n        }\n    }\n} \n                 This works for SQL views as well - you can list their names in the  \"tables\"  block above in the same way as regular tables. \n                 \n                     Restricting access to tables and views in this way will NOT prevent users from querying them using arbitrary SQL queries,  like this  for example. \n                     If you are restricting access to specific tables you should also use the  \"allow_sql\"  block to prevent users from bypassing the limit with their own SQL queries - see  Controlling the ability to execute arbitrary SQL .", "breadcrumbs": "[\"Authentication and permissions\", \"Configuring permissions in metadata.json\"]", "references": "[{\"href\": \"https://latest.datasette.io/fixtures?sql=select+*+from+facetable\", \"label\": \"like this\"}]"}, "authentication~3Aauthentication-root": {"id": "authentication:authentication-root", "page": "authentication", "ref": "authentication-root", "title": "Using the \"root\" actor", "content": "Datasette currently leaves almost all forms of authentication to plugins -  datasette-auth-github  for example. \n                 The one exception is the \"root\" account, which you can sign into while using Datasette on your local machine. This provides access to a small number of debugging features. \n                 To sign in as root, start Datasette using the  --root  command-line option, like this: \n                 $ datasette --root\nhttp://127.0.0.1:8001/-/auth-token?token=786fc524e0199d70dc9a581d851f466244e114ca92f33aa3b42a139e9388daa7\nINFO:     Started server process [25801]\nINFO:     Waiting for application startup.\nINFO:     Application startup complete.\nINFO:     Uvicorn running on http://127.0.0.1:8001 (Press CTRL+C to quit) \n                 The URL on the first line includes a one-use token which can be used to sign in as the \"root\" actor in your browser. Click on that link and then visit  http://127.0.0.1:8001/-/actor  to confirm that you are authenticated as an actor that looks like this: \n                 {\n    \"id\": \"root\"\n}", "breadcrumbs": "[\"Authentication and permissions\", \"Actors\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette-auth-github\", \"label\": \"datasette-auth-github\"}]"}, "authentication~3Aid1": {"id": "authentication:id1", "page": "authentication", "ref": "id1", "title": "Built-in permissions", "content": "This section lists all of the permission checks that are carried out by Datasette core, along with the  resource  if it was passed.", "breadcrumbs": "[\"Authentication and permissions\"]", "references": "[]"}, "authentication~3Alogoutview": {"id": "authentication:logoutview", "page": "authentication", "ref": "logoutview", "title": "The /-/logout page", "content": "The page at  /-/logout  provides the ability to log out of a  ds_actor  cookie authentication session.", "breadcrumbs": "[\"Authentication and permissions\", \"The ds_actor cookie\"]", "references": "[]"}, "authentication~3Apermissions-debug-menu": {"id": "authentication:permissions-debug-menu", "page": "authentication", "ref": "permissions-debug-menu", "title": "debug-menu", "content": "Controls if the various debug pages are displayed in the navigation menu. \n                 Default  deny .", "breadcrumbs": "[\"Authentication and permissions\", \"Built-in permissions\"]", "references": "[]"}, "authentication~3Apermissions-execute-sql": {"id": "authentication:permissions-execute-sql", "page": "authentication", "ref": "permissions-execute-sql", "title": "execute-sql", "content": "Actor is allowed to run arbitrary SQL queries against a specific database, e.g.  https://latest.datasette.io/fixtures?sql=select+100 \n                 \n                     \n                         resource  - string \n                         \n                             The name of the database \n                         \n                     \n                 \n                 Default  allow . See also  the default_allow_sql setting .", "breadcrumbs": "[\"Authentication and permissions\", \"Built-in permissions\"]", "references": "[{\"href\": \"https://latest.datasette.io/fixtures?sql=select+100\", \"label\": \"https://latest.datasette.io/fixtures?sql=select+100\"}]"}, "authentication~3Apermissions-permissions-debug": {"id": "authentication:permissions-permissions-debug", "page": "authentication", "ref": "permissions-permissions-debug", "title": "permissions-debug", "content": "Actor is allowed to view the  /-/permissions  debug page. \n                 Default  deny .", "breadcrumbs": "[\"Authentication and permissions\", \"Built-in permissions\"]", "references": "[]"}, "authentication~3Apermissions-plugins": {"id": "authentication:permissions-plugins", "page": "authentication", "ref": "permissions-plugins", "title": "Checking permissions in plugins", "content": "Datasette plugins can check if an actor has permission to perform an action using the  datasette.permission_allowed(...)  method. \n             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.", "breadcrumbs": "[\"Authentication and permissions\"]", "references": "[]"}, "authentication~3Apermissions-view-database": {"id": "authentication:permissions-view-database", "page": "authentication", "ref": "permissions-view-database", "title": "view-database", "content": "Actor is allowed to view a database page, e.g.  https://latest.datasette.io/fixtures \n                 \n                     \n                         resource  - string \n                         \n                             The name of the database \n                         \n                     \n                 \n                 Default  allow .", "breadcrumbs": "[\"Authentication and permissions\", \"Built-in permissions\"]", "references": "[{\"href\": \"https://latest.datasette.io/fixtures\", \"label\": \"https://latest.datasette.io/fixtures\"}]"}, "authentication~3Apermissions-view-database-download": {"id": "authentication:permissions-view-database-download", "page": "authentication", "ref": "permissions-view-database-download", "title": "view-database-download", "content": "Actor is allowed to download a database, e.g.  https://latest.datasette.io/fixtures.db \n                 \n                     \n                         resource  - string \n                         \n                             The name of the database \n                         \n                     \n                 \n                 Default  allow .", "breadcrumbs": "[\"Authentication and permissions\", \"Built-in permissions\"]", "references": "[{\"href\": \"https://latest.datasette.io/fixtures.db\", \"label\": \"https://latest.datasette.io/fixtures.db\"}]"}, "authentication~3Apermissions-view-instance": {"id": "authentication:permissions-view-instance", "page": "authentication", "ref": "permissions-view-instance", "title": "view-instance", "content": "Top level permission - Actor is allowed to view any pages within this instance, starting at  https://latest.datasette.io/ \n                 Default  allow .", "breadcrumbs": "[\"Authentication and permissions\", \"Built-in permissions\"]", "references": "[{\"href\": \"https://latest.datasette.io/\", \"label\": \"https://latest.datasette.io/\"}]"}, "authentication~3Apermissions-view-query": {"id": "authentication:permissions-view-query", "page": "authentication", "ref": "permissions-view-query", "title": "view-query", "content": "Actor is allowed to view (and execute) a  canned query  page, e.g.  https://latest.datasette.io/fixtures/pragma_cache_size  - this includes executing  Writable canned queries . \n                 \n                     \n                         resource  - tuple: (string, string) \n                         \n                             The name of the database, then the name of the canned query \n                         \n                     \n                 \n                 Default  allow .", "breadcrumbs": "[\"Authentication and permissions\", \"Built-in permissions\"]", "references": "[{\"href\": \"https://latest.datasette.io/fixtures/pragma_cache_size\", \"label\": \"https://latest.datasette.io/fixtures/pragma_cache_size\"}]"}, "authentication~3Apermissions-view-table": {"id": "authentication:permissions-view-table", "page": "authentication", "ref": "permissions-view-table", "title": "view-table", "content": "Actor is allowed to view a table (or view) page, e.g.  https://latest.datasette.io/fixtures/complex_foreign_keys \n                 \n                     \n                         resource  - tuple: (string, string) \n                         \n                             The name of the database, then the name of the table \n                         \n                     \n                 \n                 Default  allow .", "breadcrumbs": "[\"Authentication and permissions\", \"Built-in permissions\"]", "references": "[{\"href\": \"https://latest.datasette.io/fixtures/complex_foreign_keys\", \"label\": \"https://latest.datasette.io/fixtures/complex_foreign_keys\"}]"}, "authentication~3Apermissionsdebugview": {"id": "authentication:permissionsdebugview", "page": "authentication", "ref": "permissionsdebugview", "title": "The permissions debug tool", "content": "The debug tool at  /-/permissions  is only available to the  authenticated root user  (or any actor granted the  permissions-debug  action according to a plugin). \n             It shows the thirty most recent permission checks that have been carried out by the Datasette instance. \n             This is designed to help administrators and plugin authors understand exactly how permission checks are being carried out, in order to effectively configure Datasette's permission system.", "breadcrumbs": "[\"Authentication and permissions\"]", "references": "[]"}, "binary_data~3Abinary": {"id": "binary_data:binary", "page": "binary_data", "ref": "binary", "title": "Binary data", "content": "SQLite tables can contain binary data in  BLOB  columns. \n         Datasette includes special handling for these binary values. The Datasette interface detects binary values and provides a link to download their content, for example on  https://latest.datasette.io/fixtures/binary_data \n         \n         Binary data is represented in  .json  exports using Base64 encoding. \n         https://latest.datasette.io/fixtures/binary_data.json?_shape=array \n         [\n    {\n        \"rowid\": 1,\n        \"data\": {\n            \"$base64\": true,\n            \"encoded\": \"FRwCx60F/g==\"\n        }\n    },\n    {\n        \"rowid\": 2,\n        \"data\": {\n            \"$base64\": true,\n            \"encoded\": \"FRwDx60F/g==\"\n        }\n    },\n    {\n        \"rowid\": 3,\n        \"data\": null\n    }\n]", "breadcrumbs": "[]", "references": "[{\"href\": \"https://latest.datasette.io/fixtures/binary_data\", \"label\": \"https://latest.datasette.io/fixtures/binary_data\"}, {\"href\": \"https://latest.datasette.io/fixtures/binary_data.json?_shape=array\", \"label\": \"https://latest.datasette.io/fixtures/binary_data.json?_shape=array\"}]"}, "binary_data~3Abinary-linking": {"id": "binary_data:binary-linking", "page": "binary_data", "ref": "binary-linking", "title": "Linking to binary downloads", "content": "The  .blob  output format is used to return binary data. It requires a  _blob_column=  query string argument specifying which BLOB column should be downloaded, for example: \n             https://latest.datasette.io/fixtures/binary_data/1.blob?_blob_column=data \n             This output format can also be used to return binary data from an arbitrary SQL query. Since such queries do not specify an exact row, an additional  ?_blob_hash=  parameter can be used to specify the SHA-256 hash of the value that is being linked to. \n             Consider the query  select data from binary_data  -  demonstrated here . \n             That page links to the binary value downloads. Those links look like this: \n             https://latest.datasette.io/fixtures.blob?sql=select+data+from+binary_data&_blob_column=data&_blob_hash=f3088978da8f9aea479ffc7f631370b968d2e855eeb172bea7f6c7a04262bb6d \n             These  .blob  links are also returned in the  .csv  exports Datasette provides for binary tables and queries, since the CSV format does not have a mechanism for representing binary data.", "breadcrumbs": "[\"Binary data\"]", "references": "[{\"href\": \"https://latest.datasette.io/fixtures/binary_data/1.blob?_blob_column=data\", \"label\": \"https://latest.datasette.io/fixtures/binary_data/1.blob?_blob_column=data\"}, {\"href\": \"https://latest.datasette.io/fixtures?sql=select+data+from+binary_data\", \"label\": \"demonstrated here\"}, {\"href\": \"https://latest.datasette.io/fixtures.blob?sql=select+data+from+binary_data&_blob_column=data&_blob_hash=f3088978da8f9aea479ffc7f631370b968d2e855eeb172bea7f6c7a04262bb6d\", \"label\": \"https://latest.datasette.io/fixtures.blob?sql=select+data+from+binary_data&_blob_column=data&_blob_hash=f3088978da8f9aea479ffc7f631370b968d2e855eeb172bea7f6c7a04262bb6d\"}]"}, "binary_data~3Abinary-plugins": {"id": "binary_data:binary-plugins", "page": "binary_data", "ref": "binary-plugins", "title": "Binary plugins", "content": "Several Datasette plugins are available that change the way Datasette treats binary data. \n             \n                 \n                     datasette-render-binary  modifies Datasette's default interface to show an automatic guess at what type of binary data is being stored, along with a visual representation of the binary value that displays ASCII strings directly in the interface. \n                 \n                 \n                     datasette-render-images  detects common image formats and renders them as images directly in the Datasette interface. \n                 \n                 \n                     datasette-media  allows Datasette interfaces to be configured to serve binary files from configured SQL queries, and includes the ability to resize images directly before serving them.", "breadcrumbs": "[\"Binary data\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette-render-binary\", \"label\": \"datasette-render-binary\"}, {\"href\": \"https://github.com/simonw/datasette-render-images\", \"label\": \"datasette-render-images\"}, {\"href\": \"https://github.com/simonw/datasette-media\", \"label\": \"datasette-media\"}]"}, "changelog~3Aasgi": {"id": "changelog:asgi", "page": "changelog", "ref": "asgi", "title": "ASGI", "content": "ASGI  is the Asynchronous Server Gateway Interface standard. I've been wanting to convert Datasette into an ASGI application for over a year -  Port Datasette to ASGI #272  tracks thirteen months of intermittent development - but with Datasette 0.29 the change is finally released. This also means Datasette now runs on top of  Uvicorn  and no longer depends on  Sanic . \n                 I wrote about the significance of this change in  Porting Datasette to ASGI, and Turtles all the way down . \n                 The most exciting consequence of this change is that Datasette plugins can now take advantage of the ASGI standard.", "breadcrumbs": "[\"Changelog\", \"0.29 (2019-07-07)\"]", "references": "[{\"href\": \"https://asgi.readthedocs.io/\", \"label\": \"ASGI\"}, {\"href\": \"https://github.com/simonw/datasette/issues/272\", \"label\": \"Port Datasette to ASGI #272\"}, {\"href\": \"https://www.uvicorn.org/\", \"label\": \"Uvicorn\"}, {\"href\": \"https://github.com/huge-success/sanic\", \"label\": \"Sanic\"}, {\"href\": \"https://simonwillison.net/2019/Jun/23/datasette-asgi/\", \"label\": \"Porting Datasette to ASGI, and Turtles all the way down\"}]"}, "changelog~3Aauthentication": {"id": "changelog:authentication", "page": "changelog", "ref": "authentication", "title": "Authentication", "content": "Prior to this release the Datasette ecosystem has treated authentication as exclusively the realm of plugins, most notably through  datasette-auth-github . \n                 0.44 introduces  Authentication and permissions  as core Datasette concepts ( #699 ). This enables different plugins to share responsibility for authenticating requests - you might have one plugin that handles user accounts and another one that allows automated access via API keys, for example. \n                 You'll need to install plugins if you want full user accounts, but default Datasette can now authenticate a single root user with the new  --root  command-line option, which outputs a one-time use URL to  authenticate as a root actor  ( #784 ): \n                 $ datasette fixtures.db --root\nhttp://127.0.0.1:8001/-/auth-token?token=5b632f8cd44b868df625f5a6e2185d88eea5b22237fd3cc8773f107cc4fd6477\nINFO:     Started server process [14973]\nINFO:     Waiting for application startup.\nINFO:     Application startup complete.\nINFO:     Uvicorn running on http://127.0.0.1:8001 (Press CTRL+C to quit) \n                 Plugins can implement new ways of authenticating users using the new  actor_from_request(datasette, request)  hook.", "breadcrumbs": "[\"Changelog\", \"0.44 (2020-06-11)\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette-auth-github\", \"label\": \"datasette-auth-github\"}, {\"href\": \"https://github.com/simonw/datasette/issues/699\", \"label\": \"#699\"}, {\"href\": \"https://github.com/simonw/datasette/issues/784\", \"label\": \"#784\"}]"}, "changelog~3Abetter-plugin-documentation": {"id": "changelog:better-plugin-documentation", "page": "changelog", "ref": "better-plugin-documentation", "title": "Better plugin documentation", "content": "The plugin documentation has been re-arranged into four sections, including a brand new section on testing plugins. ( #687 ) \n                 \n                     \n                         Plugins  introduces Datasette's plugin system and describes how to install and configure plugins. \n                     \n                     \n                         Writing plugins  describes how to author plugins, from  one-off single file plugins to packaged plugins that can be published to PyPI. It also describes how to start a plugin using the new  datasette-plugin  cookiecutter template. \n                     \n                     \n                         Plugin hooks  is a full list of detailed documentation for every Datasette plugin hook. \n                     \n                     \n                         Testing plugins  describes how to write tests for Datasette plugins, using  pytest  and  HTTPX .", "breadcrumbs": "[\"Changelog\", \"0.45 (2020-07-01)\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/687\", \"label\": \"#687\"}, {\"href\": \"https://github.com/simonw/datasette-plugin\", \"label\": \"datasette-plugin\"}, {\"href\": \"https://docs.pytest.org/\", \"label\": \"pytest\"}, {\"href\": \"https://www.python-httpx.org/\", \"label\": \"HTTPX\"}]"}, "changelog~3Abinary-data": {"id": "changelog:binary-data", "page": "changelog", "ref": "binary-data", "title": "Binary data", "content": "SQLite tables can contain binary data in  BLOB  columns. Datasette now provides links for users to download this data directly from Datasette, and uses those links to make binary data available from CSV exports. See  Binary data  for more details. ( #1036  and  #1034 ).", "breadcrumbs": "[\"Changelog\", \"0.51 (2020-10-31)\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/1036\", \"label\": \"#1036\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1034\", \"label\": \"#1034\"}]"}, "changelog~3Abug-fixes": {"id": "changelog:bug-fixes", "page": "changelog", "ref": "bug-fixes", "title": "Bug fixes", "content": "Don't show the facet option in the cog menu if faceting is not allowed. ( #1683 ) \n                     \n                     \n                         ?_sort  and  ?_sort_desc  now work if the column that is being sorted has been excluded from the query using  ?_col=  or  ?_nocol= . ( #1773 ) \n                     \n                     \n                         Fixed bug where  ?_sort_desc  was duplicated in the URL every time the Apply button was clicked. ( #1738 )", "breadcrumbs": "[\"Changelog\", \"0.62 (2022-08-14)\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/1683\", \"label\": \"#1683\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1773\", \"label\": \"#1773\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1738\", \"label\": \"#1738\"}]"}, "changelog~3Abug-fixes-and-other-improvements": {"id": "changelog:bug-fixes-and-other-improvements", "page": "changelog", "ref": "bug-fixes-and-other-improvements", "title": "Bug fixes and other improvements", "content": "Custom pages  now work correctly when combined with the  base_url  setting. ( #1238 ) \n                     \n                     \n                         Fixed intermittent error displaying the index page when the user did not have permission to access one of the tables. Thanks, Guy Freeman. ( #1305 ) \n                     \n                     \n                         Columns with the name \"Link\" are no longer incorrectly displayed in bold. ( #1308 ) \n                     \n                     \n                         Fixed error caused by tables with a single quote in their names. ( #1257 ) \n                     \n                     \n                         Updated dependencies:  pytest-asyncio ,  Black ,  jinja2 ,  aiofiles ,  click , and  itsdangerous . \n                     \n                     \n                         The official Datasette Docker image now supports  apt-get install . ( #1320 ) \n                     \n                     \n                         The Heroku runtime used by  datasette publish heroku  is now  python-3.8.10 .", "breadcrumbs": "[\"Changelog\", \"0.57 (2021-06-05)\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/1238\", \"label\": \"#1238\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1305\", \"label\": \"#1305\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1308\", \"label\": \"#1308\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1257\", \"label\": \"#1257\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1320\", \"label\": \"#1320\"}]"}, "changelog~3Acode-formatting-with-black-and-prettier": {"id": "changelog:code-formatting-with-black-and-prettier", "page": "changelog", "ref": "code-formatting-with-black-and-prettier", "title": "Code formatting with Black and Prettier", "content": "Datasette adopted  Black  for opinionated Python code formatting in June 2019. Datasette now also embraces  Prettier  for JavaScript formatting, which like Black is enforced by tests in continuous integration. Instructions for using these two tools can be found in the new section on  Code formatting  in the contributors documentation. ( #1167 )", "breadcrumbs": "[\"Changelog\", \"0.54 (2021-01-25)\"]", "references": "[{\"href\": \"https://github.com/psf/black\", \"label\": \"Black\"}, {\"href\": \"https://prettier.io/\", \"label\": \"Prettier\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1167\", \"label\": \"#1167\"}]"}, "changelog~3Acontrol-http-caching-with-ttl": {"id": "changelog:control-http-caching-with-ttl", "page": "changelog", "ref": "control-http-caching-with-ttl", "title": "Control HTTP caching with ?_ttl=", "content": "You can now customize the HTTP max-age header that is sent on a per-URL basis, using the new  ?_ttl=  query string parameter. \n                 You can set this to any value in seconds, or you can set it to 0 to disable HTTP caching entirely. \n                 Consider for example this query which returns a randomly selected member of the Avengers: \n                 select * from [avengers/avengers] order by random() limit 1 \n                 If you hit the following page repeatedly you will get the same result, due to HTTP caching: \n                 /fivethirtyeight?sql=select+*+from+%5Bavengers%2Favengers%5D+order+by+random%28%29+limit+1 \n                 By adding  ?_ttl=0  to the zero you can ensure the page will not be cached and get back a different super hero every time: \n                 /fivethirtyeight?sql=select+*+from+%5Bavengers%2Favengers%5D+order+by+random%28%29+limit+1&_ttl=0", "breadcrumbs": "[\"Changelog\", \"0.23 (2018-06-18)\"]", "references": "[{\"href\": \"https://fivethirtyeight.datasettes.com/fivethirtyeight?sql=select+*+from+%5Bavengers%2Favengers%5D+order+by+random%28%29+limit+1\", \"label\": \"/fivethirtyeight?sql=select+*+from+%5Bavengers%2Favengers%5D+order+by+random%28%29+limit+1\"}, {\"href\": \"https://fivethirtyeight.datasettes.com/fivethirtyeight?sql=select+*+from+%5Bavengers%2Favengers%5D+order+by+random%28%29+limit+1&_ttl=0\", \"label\": \"/fivethirtyeight?sql=select+*+from+%5Bavengers%2Favengers%5D+order+by+random%28%29+limit+1&_ttl=0\"}]"}, "changelog~3Acookie-methods": {"id": "changelog:cookie-methods", "page": "changelog", "ref": "cookie-methods", "title": "Cookie methods", "content": "Plugins can now use the new  response.set_cookie()  method to set cookies. \n                 A new  request.cookies  method on the :ref:internals_request` can be used to read incoming cookies.", "breadcrumbs": "[\"Changelog\", \"0.44 (2020-06-11)\"]", "references": "[]"}, "changelog~3Acsrf-protection": {"id": "changelog:csrf-protection", "page": "changelog", "ref": "csrf-protection", "title": "CSRF protection", "content": "Since writable canned queries are built using POST forms, Datasette now ships with  CSRF protection  ( #798 ). This applies automatically to any POST request, which means plugins need to include a  csrftoken  in any POST forms that they render. They can do that like so: \n                 <input type=\"hidden\" name=\"csrftoken\" value=\"{{ csrftoken() }}\">", "breadcrumbs": "[\"Changelog\", \"0.44 (2020-06-11)\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/798\", \"label\": \"#798\"}]"}, "changelog~3Acsv-export": {"id": "changelog:csv-export", "page": "changelog", "ref": "csv-export", "title": "CSV export", "content": "Any Datasette table, view or custom SQL query can now be exported as CSV. \n                 \n                 Check out the  CSV export documentation  for more details, or\n                    try the feature out on\n                     https://fivethirtyeight.datasettes.com/fivethirtyeight/bechdel%2Fmovies \n                 If your table has more than  max_returned_rows  (default 1,000)\n                    Datasette provides the option to  stream all rows . This option takes advantage\n                    of async Python and Datasette's efficient  pagination  to\n                    iterate through the entire matching result set and stream it back as a\n                    downloadable CSV file.", "breadcrumbs": "[\"Changelog\", \"0.23 (2018-06-18)\"]", "references": "[{\"href\": \"https://fivethirtyeight.datasettes.com/fivethirtyeight/bechdel%2Fmovies\", \"label\": \"https://fivethirtyeight.datasettes.com/fivethirtyeight/bechdel%2Fmovies\"}]"}, "changelog~3Adocumentation": {"id": "changelog:documentation", "page": "changelog", "ref": "documentation", "title": "Documentation", "content": "New tutorial:  Cleaning data with sqlite-utils and Datasette . \n                     \n                     \n                         Screenshots in the documentation are now maintained using  shot-scraper , as described in  Automating screenshots for the Datasette documentation using shot-scraper . ( #1844 ) \n                     \n                     \n                         More detailed command descriptions on the  CLI reference  page. ( #1787 ) \n                     \n                     \n                         New documentation on  Running Datasette using OpenRC  - thanks, Adam Simpson. ( #1825 )", "breadcrumbs": "[\"Changelog\", \"0.63 (2022-10-27)\"]", "references": "[{\"href\": \"https://datasette.io/tutorials/clean-data\", \"label\": \"Cleaning data with sqlite-utils and Datasette\"}, {\"href\": \"https://shot-scraper.datasette.io/\", \"label\": \"shot-scraper\"}, {\"href\": \"https://simonwillison.net/2022/Oct/14/automating-screenshots/\", \"label\": \"Automating screenshots for the Datasette documentation using shot-scraper\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1844\", \"label\": \"#1844\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1787\", \"label\": \"#1787\"}, {\"href\": \"https://github.com/simonw/datasette/pull/1825\", \"label\": \"#1825\"}]"}, "changelog~3Afacet-by-date": {"id": "changelog:facet-by-date", "page": "changelog", "ref": "facet-by-date", "title": "Facet by date", "content": "If a column contains datetime values, Datasette can now facet that column by date. ( #481 )", "breadcrumbs": "[\"Changelog\", \"0.29 (2019-07-07)\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/481\", \"label\": \"#481\"}]"}, "changelog~3Afaceting": {"id": "changelog:faceting", "page": "changelog", "ref": "faceting", "title": "Faceting", "content": "The number of unique values in a facet is now always displayed. Previously it was only displayed if the user specified  ?_facet_size=max . ( #1556 ) \n                     \n                     \n                         Facets of type  date  or  array  can now be configured in  metadata.json , see  Facets in metadata.json . Thanks, David Larlet. ( #1552 ) \n                     \n                     \n                         New  ?_nosuggest=1  parameter for table views, which disables facet suggestion. ( #1557 ) \n                     \n                     \n                         Fixed bug where  ?_facet_array=tags&_facet=tags  would only display one of the two selected facets. ( #625 )", "breadcrumbs": "[\"Changelog\", \"0.60 (2022-01-13)\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/1556\", \"label\": \"#1556\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1552\", \"label\": \"#1552\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1557\", \"label\": \"#1557\"}, {\"href\": \"https://github.com/simonw/datasette/issues/625\", \"label\": \"#625\"}]"}, "changelog~3Afeatures": {"id": "changelog:features", "page": "changelog", "ref": "features", "title": "Features", "content": "Now tested against Python 3.11. Docker containers used by  datasette publish  and  datasette package  both now use that version of Python. ( #1853 ) \n                     \n                     \n                         --load-extension  option now supports entrypoints. Thanks, Alex Garcia. ( #1789 ) \n                     \n                     \n                         Facet size can now be set per-table with the new  facet_size  table metadata option. ( #1804 ) \n                     \n                     \n                         The  truncate_cells_html  setting now also affects long URLs in columns. ( #1805 ) \n                     \n                     \n                         The non-JavaScript SQL editor textarea now increases height to fit the SQL query. ( #1786 ) \n                     \n                     \n                         Facets are now displayed with better line-breaks in long values. Thanks, Daniel Rech. ( #1794 ) \n                     \n                     \n                         The  settings.json  file used in  Configuration directory mode  is now validated on startup. ( #1816 ) \n                     \n                     \n                         SQL queries can now include leading SQL comments, using  /* ... */  or  -- ...  syntax. Thanks,  Charles Nepote. ( #1860 ) \n                     \n                     \n                         SQL query is now re-displayed when terminated with a time limit error. ( #1819 ) \n                     \n                     \n                         The  inspect data  mechanism is now used to speed up server startup - thanks, Forest Gregg. ( #1834 ) \n                     \n                     \n                         In  Configuration directory mode  databases with filenames ending in  .sqlite  or  .sqlite3  are now automatically added to the Datasette instance. ( #1646 ) \n                     \n                     \n                         Breadcrumb navigation display now respects the current user's permissions. ( #1831 )", "breadcrumbs": "[\"Changelog\", \"0.63 (2022-10-27)\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/1853\", \"label\": \"#1853\"}, {\"href\": \"https://github.com/simonw/datasette/pull/1789\", \"label\": \"#1789\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1804\", \"label\": \"#1804\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1805\", \"label\": \"#1805\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1786\", \"label\": \"#1786\"}, {\"href\": \"https://github.com/simonw/datasette/pull/1794\", \"label\": \"#1794\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1816\", \"label\": \"#1816\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1860\", \"label\": \"#1860\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1819\", \"label\": \"#1819\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1834\", \"label\": \"#1834\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1646\", \"label\": \"#1646\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1831\", \"label\": \"#1831\"}]"}, "changelog~3Aflash-messages": {"id": "changelog:flash-messages", "page": "changelog", "ref": "flash-messages", "title": "Flash messages", "content": "Writable canned queries needed a mechanism to let the user know that the query has been successfully executed. The new flash messaging system ( #790 ) allows messages to persist in signed cookies which are then displayed to the user on the next page that they visit. Plugins can use this mechanism to display their own messages, see  .add_message(request, message, type=datasette.INFO)  for details. \n                 You can try out the new messages using the  /-/messages  debug tool, for example at  https://latest.datasette.io/-/messages", "breadcrumbs": "[\"Changelog\", \"0.44 (2020-06-11)\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/790\", \"label\": \"#790\"}, {\"href\": \"https://latest.datasette.io/-/messages\", \"label\": \"https://latest.datasette.io/-/messages\"}]"}, "changelog~3Aforeign-key-expansions": {"id": "changelog:foreign-key-expansions", "page": "changelog", "ref": "foreign-key-expansions", "title": "Foreign key expansions", "content": "When Datasette detects a foreign key reference it attempts to resolve a label\n                    for that reference (automatically or using the  Specifying the label column for a table  metadata\n                    option) so it can display a link to the associated row. \n                 This expansion is now also available for JSON and CSV representations of the\n                    table, using the new  _labels=on  query string option. See\n                     Expanding foreign key references  for more details.", "breadcrumbs": "[\"Changelog\", \"0.23 (2018-06-18)\"]", "references": "[]"}, "changelog~3Aid1": {"id": "changelog:id1", "page": "changelog", "ref": "id1", "title": "Changelog", "content": "", "breadcrumbs": "[]", "references": "[]"}, "changelog~3Aid10": {"id": "changelog:id10", "page": "changelog", "ref": "id10", "title": "0.64.3 (2023-04-27)", "content": "Added  pip  and  setuptools  as explicit dependencies. This fixes a bug where Datasette could not be installed using  Rye . ( #2065 )", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/mitsuhiko/rye\", \"label\": \"Rye\"}, {\"href\": \"https://github.com/simonw/datasette/issues/2065\", \"label\": \"#2065\"}]"}, "changelog~3Aid105": {"id": "changelog:id105", "page": "changelog", "ref": "id105", "title": "0.23.2 (2018-07-07)", "content": "Minor bugfix and documentation release. \n             \n                 \n                     CSV export now respects  --cors , fixes  #326 \n                 \n                 \n                     Installation instructions , including docker image - closes  #328 \n                 \n                 \n                     Fix for row pages for tables with / in, closes  #325", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/326\", \"label\": \"#326\"}, {\"href\": \"https://github.com/simonw/datasette/issues/328\", \"label\": \"#328\"}, {\"href\": \"https://github.com/simonw/datasette/issues/325\", \"label\": \"#325\"}]"}, "changelog~3Aid109": {"id": "changelog:id109", "page": "changelog", "ref": "id109", "title": "0.23.1 (2018-06-21)", "content": "Minor bugfix release. \n             \n                 \n                     Correctly display empty strings in HTML table, closes  #314 \n                 \n                 \n                     Allow \".\" in database filenames, closes  #302 \n                 \n                 \n                     404s ending in slash redirect to remove that slash, closes  #309 \n                 \n                 \n                     Fixed incorrect display of compound primary keys with foreign key\n                        references. Closes  #319 \n                 \n                 \n                     Docs + example of canned SQL query using || concatenation. Closes  #321 \n                 \n                 \n                     Correctly display facets with value of 0 - closes  #318 \n                 \n                 \n                     Default 'expand labels' to checked in CSV advanced export", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/314\", \"label\": \"#314\"}, {\"href\": \"https://github.com/simonw/datasette/issues/302\", \"label\": \"#302\"}, {\"href\": \"https://github.com/simonw/datasette/issues/309\", \"label\": \"#309\"}, {\"href\": \"https://github.com/simonw/datasette/issues/319\", \"label\": \"#319\"}, {\"href\": \"https://github.com/simonw/datasette/issues/321\", \"label\": \"#321\"}, {\"href\": \"https://github.com/simonw/datasette/issues/318\", \"label\": \"#318\"}]"}, "changelog~3Aid11": {"id": "changelog:id11", "page": "changelog", "ref": "id11", "title": "0.64.2 (2023-03-08)", "content": "Fixed a bug with  datasette publish cloudrun  where deploys all used the same Docker image tag. This was mostly inconsequential as the service is deployed as soon as the image has been pushed to the registry, but could result in the incorrect image being deployed if two different deploys for two separate services ran at exactly the same time. ( #2036 )", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/2036\", \"label\": \"#2036\"}]"}, "changelog~3Aid116": {"id": "changelog:id116", "page": "changelog", "ref": "id116", "title": "0.23 (2018-06-18)", "content": "This release features CSV export, improved options for foreign key expansions,\n                new configuration settings and improved support for SpatiaLite. \n             See  datasette/compare/0.22.1...0.23  for a full list of\n                commits added since the last release.", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/compare/0.22.1...0.23\", \"label\": \"datasette/compare/0.22.1...0.23\"}]"}, "changelog~3Aid117": {"id": "changelog:id117", "page": "changelog", "ref": "id117", "title": "0.22.1 (2018-05-23)", "content": "Bugfix release, plus we now use  versioneer  for our version numbers. \n             \n                 \n                     Faceting no longer breaks pagination, fixes  #282 \n                 \n                 \n                     Add  __version_info__  derived from  __version__  [Robert Gieseke] \n                     This might be tuple of more than two values (major and minor\n                        version) if commits have been made after a release. \n                 \n                 \n                     Add version number support with Versioneer. [Robert Gieseke] \n                     Versioneer Licence:\n                        Public Domain (CC0-1.0) \n                     Closes  #273 \n                 \n                 \n                     Refactor inspect logic [Russ Garrett]", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/warner/python-versioneer\", \"label\": \"versioneer\"}, {\"href\": \"https://github.com/simonw/datasette/issues/282\", \"label\": \"#282\"}, {\"href\": \"https://github.com/simonw/datasette/issues/273\", \"label\": \"#273\"}]"}, "changelog~3Aid12": {"id": "changelog:id12", "page": "changelog", "ref": "id12", "title": "0.64.1 (2023-01-11)", "content": "Documentation now links to a current source of information for installing Python 3. ( #1987 ) \n                 \n                 \n                     Incorrectly calling the Datasette constructor using  Datasette(\"path/to/data.db\")  instead of  Datasette([\"path/to/data.db\"])  now returns a useful error message. ( #1985 )", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/1987\", \"label\": \"#1987\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1985\", \"label\": \"#1985\"}]"}, "changelog~3Aid120": {"id": "changelog:id120", "page": "changelog", "ref": "id120", "title": "0.22 (2018-05-20)", "content": "The big new feature in this release is  Facets . Datasette can now apply faceted browse to any column in any table. It will also suggest possible facets. See the  Datasette Facets  announcement post for more details. \n             In addition to the work on facets: \n             \n                 \n                     Added  docs for introspection endpoints \n                 \n                 \n                     New  --config  option, added  --help-config , closes  #274 \n                     Removed the  --page_size=  argument to  datasette serve  in favour of: \n                     datasette serve --config default_page_size:50 mydb.db \n                     Added new help section: \n                     $ datasette --help-config\nConfig options:\n  default_page_size            Default page size for the table view\n                               (default=100)\n  max_returned_rows            Maximum rows that can be returned from a table\n                               or custom query (default=1000)\n  sql_time_limit_ms            Time limit for a SQL query in milliseconds\n                               (default=1000)\n  default_facet_size           Number of values to return for requested facets\n                               (default=30)\n  facet_time_limit_ms          Time limit for calculating a requested facet\n                               (default=200)\n  facet_suggest_time_limit_ms  Time limit for calculating a suggested facet\n                               (default=50) \n                 \n                 \n                     Only apply responsive table styles to  .rows-and-column \n                     Otherwise they interfere with tables in the description, e.g. on\n                         https://fivethirtyeight.datasettes.com/fivethirtyeight/nba-elo%2Fnbaallelo \n                 \n                 \n                     Refactored views into new  views/  modules, refs  #256 \n                 \n                 \n                     Documentation for SQLite full-text search  support, closes  #253 \n                 \n                 \n                     /-/versions  now includes SQLite  fts_versions , closes  #252", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://simonwillison.net/2018/May/20/datasette-facets/\", \"label\": \"Datasette Facets\"}, {\"href\": \"https://docs.datasette.io/en/stable/introspection.html\", \"label\": \"docs for introspection endpoints\"}, {\"href\": \"https://github.com/simonw/datasette/issues/274\", \"label\": \"#274\"}, {\"href\": \"https://fivethirtyeight.datasettes.com/fivethirtyeight/nba-elo%2Fnbaallelo\", \"label\": \"https://fivethirtyeight.datasettes.com/fivethirtyeight/nba-elo%2Fnbaallelo\"}, {\"href\": \"https://github.com/simonw/datasette/issues/256\", \"label\": \"#256\"}, {\"href\": \"https://docs.datasette.io/en/stable/full_text_search.html\", \"label\": \"Documentation for SQLite full-text search\"}, {\"href\": \"https://github.com/simonw/datasette/issues/253\", \"label\": \"#253\"}, {\"href\": \"https://github.com/simonw/datasette/issues/252\", \"label\": \"#252\"}]"}, "changelog~3Aid125": {"id": "changelog:id125", "page": "changelog", "ref": "id125", "title": "0.21 (2018-05-05)", "content": "New JSON  _shape=  options, the ability to set table  _size=  and a mechanism for searching within specific columns. \n             \n                 \n                     Default tests to using a longer timelimit \n                     Every now and then a test will fail in Travis CI on Python 3.5 because it hit\n                        the default 20ms SQL time limit. \n                     Test fixtures now default to a 200ms time limit, and we only use the 20ms time\n                        limit for the specific test that tests query interruption. This should make\n                        our tests on Python 3.5 in Travis much more stable. \n                 \n                 \n                     Support  _search_COLUMN=text  searches, closes  #237 \n                 \n                 \n                     Show version on  /-/plugins  page, closes  #248 \n                 \n                 \n                     ?_size=max  option, closes  #249 \n                 \n                 \n                     Added  /-/versions  and  /-/versions.json , closes  #244 \n                     Sample output: \n                     {\n  \"python\": {\n    \"version\": \"3.6.3\",\n    \"full\": \"3.6.3 (default, Oct  4 2017, 06:09:38) \\n[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.37)]\"\n  },\n  \"datasette\": {\n    \"version\": \"0.20\"\n  },\n  \"sqlite\": {\n    \"version\": \"3.23.1\",\n    \"extensions\": {\n      \"json1\": null,\n      \"spatialite\": \"4.3.0a\"\n    }\n  }\n} \n                 \n                 \n                     Renamed  ?_sql_time_limit_ms=  to  ?_timelimit , closes  #242 \n                 \n                 \n                     New  ?_shape=array  option + tweaks to  _shape , closes  #245 \n                     \n                         \n                             Default is now  ?_shape=arrays  (renamed from  lists ) \n                         \n                         \n                             New  ?_shape=array  returns an array of objects as the root object \n                         \n                         \n                             Changed  ?_shape=object  to return the object as the root \n                         \n                         \n                             Updated docs \n                         \n                     \n                 \n                 \n                     FTS tables now detected by  inspect() , closes  #240 \n                 \n                 \n                     New  ?_size=XXX  query string parameter for table view, closes  #229 \n                     Also added documentation for all of the  _special  arguments. \n                     Plus deleted some duplicate logic implementing  _group_count . \n                 \n                 \n                     If  max_returned_rows==page_size , increment  max_returned_rows  - fixes  #230 \n                 \n                 \n                     New  hidden: True  option for table metadata, closes  #239 \n                 \n                 \n                     Hide  idx_*  tables if spatialite detected, closes  #228 \n                 \n                 \n                     Added  class=rows-and-columns  to custom query results table \n                 \n                 \n                     Added CSS class  rows-and-columns  to main table \n                 \n                 \n                     label_column  option in  metadata.json  - closes  #234", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/237\", \"label\": \"#237\"}, {\"href\": \"https://github.com/simonw/datasette/issues/248\", \"label\": \"#248\"}, {\"href\": \"https://github.com/simonw/datasette/issues/249\", \"label\": \"#249\"}, {\"href\": \"https://github.com/simonw/datasette/issues/244\", \"label\": \"#244\"}, {\"href\": \"https://github.com/simonw/datasette/issues/242\", \"label\": \"#242\"}, {\"href\": \"https://github.com/simonw/datasette/issues/245\", \"label\": \"#245\"}, {\"href\": \"https://github.com/simonw/datasette/issues/240\", \"label\": \"#240\"}, {\"href\": \"https://github.com/simonw/datasette/issues/229\", \"label\": \"#229\"}, {\"href\": \"https://github.com/simonw/datasette/issues/230\", \"label\": \"#230\"}, {\"href\": \"https://github.com/simonw/datasette/issues/239\", \"label\": \"#239\"}, {\"href\": \"https://github.com/simonw/datasette/issues/228\", \"label\": \"#228\"}, {\"href\": \"https://github.com/simonw/datasette/issues/234\", \"label\": \"#234\"}]"}, "changelog~3Aid13": {"id": "changelog:id13", "page": "changelog", "ref": "id13", "title": "0.64 (2023-01-09)", "content": "Datasette now  strongly recommends against allowing arbitrary SQL queries if you are using SpatiaLite . SpatiaLite includes SQL functions that could cause the Datasette server to crash. See  SpatiaLite  for more details. \n                 \n                 \n                     New  default_allow_sql  setting, providing an easier way to disable all arbitrary SQL execution by end users:  datasette --setting default_allow_sql off . See also  Controlling the ability to execute arbitrary SQL . ( #1409 ) \n                 \n                 \n                     Building a location to time zone API with SpatiaLite  is a new Datasette tutorial showing how to safely use SpatiaLite to create a location to time zone API. \n                 \n                 \n                     New documentation about  how to debug problems loading SQLite extensions . The error message shown when an extension cannot be loaded has also been improved. ( #1979 ) \n                 \n                 \n                     Fixed an accessibility issue: the  <select>  elements in the table filter form now show an outline when they are currently focused. ( #1771 )", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/1409\", \"label\": \"#1409\"}, {\"href\": \"https://datasette.io/tutorials/spatialite\", \"label\": \"Building a location to time zone API with SpatiaLite\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1979\", \"label\": \"#1979\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1771\", \"label\": \"#1771\"}]"}, "changelog~3Aid138": {"id": "changelog:id138", "page": "changelog", "ref": "id138", "title": "0.20 (2018-04-20)", "content": "Mostly new work on the  Plugins  mechanism: plugins can now bundle static assets and custom templates, and  datasette publish  has a new  --install=name-of-plugin  option. \n             \n                 \n                     Add col-X classes to HTML table on custom query page \n                 \n                 \n                     Fixed out-dated template in documentation \n                 \n                 \n                     Plugins can now bundle custom templates,  #224 \n                 \n                 \n                     Added /-/metadata /-/plugins /-/inspect,  #225 \n                 \n                 \n                     Documentation for --install option, refs  #223 \n                 \n                 \n                     Datasette publish/package --install option,  #223 \n                 \n                 \n                     Fix for plugins in Python 3.5,  #222 \n                 \n                 \n                     New plugin hooks: extra_css_urls() and extra_js_urls(),  #214 \n                 \n                 \n                     /-/static-plugins/PLUGIN_NAME/ now serves static/ from plugins \n                 \n                 \n                     <th> now gets class=\"col-X\" - plus added col-X documentation \n                 \n                 \n                     Use to_css_class for table cell column classes \n                     This ensures that columns with spaces in the name will still\n                        generate usable CSS class names. Refs  #209 \n                 \n                 \n                     Add column name classes to <td>s, make PK bold [Russ Garrett] \n                 \n                 \n                     Don't duplicate simple primary keys in the link column [Russ Garrett] \n                     When there's a simple (single-column) primary key, it looks weird to\n                        duplicate it in the link column. \n                     This change removes the second PK column and treats the link column as\n                        if it were the PK column from a header/sorting perspective. \n                 \n                 \n                     Correct escaping for HTML display of row links [Russ Garrett] \n                 \n                 \n                     Longer time limit for test_paginate_compound_keys \n                     It was failing intermittently in Travis - see  #209 \n                 \n                 \n                     Use application/octet-stream for downloadable databases \n                 \n                 \n                     Updated PyPI classifiers \n                 \n                 \n                     Updated PyPI link to pypi.org", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/224\", \"label\": \"#224\"}, {\"href\": \"https://github.com/simonw/datasette/issues/225\", \"label\": \"#225\"}, {\"href\": \"https://github.com/simonw/datasette/issues/223\", \"label\": \"#223\"}, {\"href\": \"https://github.com/simonw/datasette/issues/223\", \"label\": \"#223\"}, {\"href\": \"https://github.com/simonw/datasette/issues/222\", \"label\": \"#222\"}, {\"href\": \"https://github.com/simonw/datasette/issues/214\", \"label\": \"#214\"}, {\"href\": \"https://github.com/simonw/datasette/issues/209\", \"label\": \"#209\"}, {\"href\": \"https://github.com/simonw/datasette/issues/209\", \"label\": \"#209\"}]"}, "changelog~3Aid14": {"id": "changelog:id14", "page": "changelog", "ref": "id14", "title": "0.63.3 (2022-12-17)", "content": "Fixed a bug where  datasette --root , when running in Docker, would only output the URL to sign in as root when the server shut down, not when it started up. ( #1958 ) \n                 \n                 \n                     You no longer need to ensure  await datasette.invoke_startup()  has been called in order for Datasette to start correctly serving requests - this is now handled automatically the first time the server receives a request. This fixes a bug experienced when Datasette is served directly by an ASGI application server such as Uvicorn or Gunicorn. It also fixes a bug with the  datasette-gunicorn  plugin. ( #1955 )", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/1958\", \"label\": \"#1958\"}, {\"href\": \"https://datasette.io/plugins/datasette-gunicorn\", \"label\": \"datasette-gunicorn\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1955\", \"label\": \"#1955\"}]"}, "changelog~3Aid147": {"id": "changelog:id147", "page": "changelog", "ref": "id147", "title": "0.19 (2018-04-16)", "content": "This is the first preview of the new Datasette plugins mechanism. Only two\n                plugin hooks are available so far - for custom SQL functions and custom template\n                filters. There's plenty more to come - read  the documentation  and get involved in\n                 the tracking ticket  if you\n                have feedback on the direction so far. \n             \n                 \n                     Fix for  _sort_desc=sortable_with_nulls  test, refs  #216 \n                 \n                 \n                     Fixed  #216  - paginate correctly when sorting by nullable column \n                 \n                 \n                     Initial documentation for plugins, closes  #213 \n                     https://docs.datasette.io/en/stable/plugins.html \n                 \n                 \n                     New  --plugins-dir=plugins/  option ( #212 ) \n                     New option causing Datasette to load and evaluate all of the Python files in\n                        the specified directory and register any plugins that are defined in those\n                        files. \n                     This new option is available for the following commands: \n                     datasette serve mydb.db --plugins-dir=plugins/\ndatasette publish now/heroku mydb.db --plugins-dir=plugins/\ndatasette package mydb.db --plugins-dir=plugins/ \n                 \n                 \n                     Start of the plugin system, based on pluggy ( #210 ) \n                     Uses  https://pluggy.readthedocs.io/  originally created for the py.test project \n                     We're starting with two plugin hooks: \n                     prepare_connection(conn) \n                     This is called when a new SQLite connection is created. It can be used to register custom SQL functions. \n                     prepare_jinja2_environment(env) \n                     This is called with the Jinja2 environment. It can be used to register custom template tags and filters. \n                     An example plugin which uses these two hooks can be found at  https://github.com/simonw/datasette-plugin-demos  or installed using  pip install datasette-plugin-demos \n                     Refs  #14 \n                 \n                 \n                     Return HTTP 405 on InvalidUsage rather than 500. [Russ Garrett] \n                     This also stops it filling up the logs. This happens for HEAD requests\n                        at the moment - which perhaps should be handled better, but that's a\n                        different issue.", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://docs.datasette.io/en/stable/plugins.html\", \"label\": \"the documentation\"}, {\"href\": \"https://github.com/simonw/datasette/issues/14\", \"label\": \"the tracking ticket\"}, {\"href\": \"https://github.com/simonw/datasette/issues/216\", \"label\": \"#216\"}, {\"href\": \"https://github.com/simonw/datasette/issues/216\", \"label\": \"#216\"}, {\"href\": \"https://github.com/simonw/datasette/issues/213\", \"label\": \"#213\"}, {\"href\": \"https://docs.datasette.io/en/stable/plugins.html\", \"label\": \"https://docs.datasette.io/en/stable/plugins.html\"}, {\"href\": \"https://github.com/simonw/datasette/issues/212\", \"label\": \"#212\"}, {\"href\": \"https://github.com/simonw/datasette/issues/14\", \"label\": \"#210\"}, {\"href\": \"https://pluggy.readthedocs.io/\", \"label\": \"https://pluggy.readthedocs.io/\"}, {\"href\": \"https://github.com/simonw/datasette-plugin-demos\", \"label\": \"https://github.com/simonw/datasette-plugin-demos\"}, {\"href\": \"https://github.com/simonw/datasette/issues/14\", \"label\": \"#14\"}]"}, "changelog~3Aid15": {"id": "changelog:id15", "page": "changelog", "ref": "id15", "title": "0.63.2 (2022-11-18)", "content": "Fixed a bug in  datasette publish heroku  where deployments failed due to an older version of Python being requested. ( #1905 ) \n                 \n                 \n                     New  datasette publish heroku --generate-dir <dir>  option for generating a Heroku deployment directory without deploying it.", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/1905\", \"label\": \"#1905\"}]"}, "changelog~3Aid154": {"id": "changelog:id154", "page": "changelog", "ref": "id154", "title": "0.18 (2018-04-14)", "content": "This release introduces  support for units ,\n                contributed by Russ Garrett ( #203 ).\n                You can now optionally specify the units for specific columns using  metadata.json .\n                Once specified, units will be displayed in the HTML view of your table. They also become\n                available for use in filters - if a column is configured with a unit of distance, you can\n                request all rows where that column is less than 50 meters or more than 20 feet for example. \n             \n                 \n                     Link foreign keys which don't have labels. [Russ Garrett] \n                     This renders unlabeled FKs as simple links. \n                     Also includes bonus fixes for two minor issues: \n                     \n                         \n                             In foreign key link hrefs the primary key was escaped using HTML\n                                escaping rather than URL escaping. This broke some non-integer PKs. \n                         \n                         \n                             Print tracebacks to console when handling 500 errors. \n                         \n                     \n                 \n                 \n                     Fix SQLite error when loading rows with no incoming FKs. [Russ\n                        Garrett] \n                     This fixes an error caused by an invalid query when loading incoming FKs. \n                     The error was ignored due to async but it still got printed to the\n                        console. \n                 \n                 \n                     Allow custom units to be registered with Pint. [Russ Garrett] \n                 \n                 \n                     Support units in filters. [Russ Garrett] \n                 \n                 \n                     Tidy up units support. [Russ Garrett] \n                     \n                         \n                             Add units to exported JSON \n                         \n                         \n                             Units key in metadata skeleton \n                         \n                         \n                             Docs \n                         \n                     \n                 \n                 \n                     Initial units support. [Russ Garrett] \n                     Add support for specifying units for a column in  metadata.json  and\n                        rendering them on display using\n                         pint", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://docs.datasette.io/en/stable/metadata.html#specifying-units-for-a-column\", \"label\": \"support for units\"}, {\"href\": \"https://github.com/simonw/datasette/issues/203\", \"label\": \"#203\"}, {\"href\": \"https://pint.readthedocs.io/en/latest/\", \"label\": \"pint\"}]"}, "changelog~3Aid156": {"id": "changelog:id156", "page": "changelog", "ref": "id156", "title": "0.17 (2018-04-13)", "content": "Release 0.17 to fix issues with PyPI", "breadcrumbs": "[\"Changelog\"]", "references": "[]"}, "changelog~3Aid157": {"id": "changelog:id157", "page": "changelog", "ref": "id157", "title": "0.16 (2018-04-13)", "content": "Better mechanism for handling errors; 404s for missing table/database \n                     New error mechanism closes  #193 \n                     404s for missing tables/databases closes  #184 \n                 \n                 \n                     long_description in markdown for the new PyPI \n                 \n                 \n                     Hide SpatiaLite system tables. [Russ Garrett] \n                 \n                 \n                     Allow  explain select  /  explain query plan select   #201 \n                 \n                 \n                     Datasette inspect now finds primary_keys  #195 \n                 \n                 \n                     Ability to sort using form fields (for mobile portrait mode)  #199 \n                     We now display sort options as a select box plus a descending checkbox, which\n                        means you can apply sort orders even in portrait mode on a mobile phone where\n                        the column headers are hidden.", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/193\", \"label\": \"#193\"}, {\"href\": \"https://github.com/simonw/datasette/issues/184\", \"label\": \"#184\"}, {\"href\": \"https://github.com/simonw/datasette/issues/201\", \"label\": \"#201\"}, {\"href\": \"https://github.com/simonw/datasette/issues/195\", \"label\": \"#195\"}, {\"href\": \"https://github.com/simonw/datasette/issues/199\", \"label\": \"#199\"}]"}, "changelog~3Aid16": {"id": "changelog:id16", "page": "changelog", "ref": "id16", "title": "0.63.1 (2022-11-10)", "content": "Fixed a bug where Datasette's table filter form would not redirect correctly when run behind a proxy using the  base_url  setting. ( #1883 ) \n                 \n                 \n                     SQL query is now shown wrapped in a  <textarea>  if a query exceeds a time limit. ( #1876 ) \n                 \n                 \n                     Fixed an intermittent \"Too many open files\" error while running the test suite. ( #1843 ) \n                 \n                 \n                     New  db.close()  internal method.", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/1883\", \"label\": \"#1883\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1876\", \"label\": \"#1876\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1843\", \"label\": \"#1843\"}]"}, "changelog~3Aid163": {"id": "changelog:id163", "page": "changelog", "ref": "id163", "title": "0.15 (2018-04-09)", "content": "The biggest new feature in this release is the ability to sort by column. On the\n                table page the column headers can now be clicked to apply sort (or descending\n                sort), or you can specify  ?_sort=column  or  ?_sort_desc=column  directly\n                in the URL. \n             \n                 \n                     table_rows  =>  table_rows_count ,  filtered_table_rows  =>\n                         filtered_table_rows_count \n                     Renamed properties. Closes  #194 \n                 \n                 \n                     New  sortable_columns  option in  metadata.json  to control sort options. \n                     You can now explicitly set which columns in a table can be used for sorting\n                        using the  _sort  and  _sort_desc  arguments using  metadata.json : \n                     {\n    \"databases\": {\n        \"database1\": {\n            \"tables\": {\n                \"example_table\": {\n                    \"sortable_columns\": [\n                        \"height\",\n                        \"weight\"\n                    ]\n                }\n            }\n        }\n    }\n} \n                     Refs  #189 \n                 \n                 \n                     Column headers now link to sort/desc sort - refs  #189 \n                 \n                 \n                     _sort  and  _sort_desc  parameters for table views \n                     Allows for paginated sorted results based on a specified column. \n                     Refs  #189 \n                 \n                 \n                     Total row count now correct even if  _next  applied \n                 \n                 \n                     Use .custom_sql() for _group_count implementation (refs  #150 ) \n                 \n                 \n                     Make HTML title more readable in query template ( #180 ) [Ryan Pitts] \n                 \n                 \n                     New  ?_shape=objects/object/lists  param for JSON API ( #192 ) \n                     New  _shape=  parameter replacing old  .jsono  extension \n                     Now instead of this: \n                     /database/table.jsono \n                     We use the  _shape  parameter like this: \n                     /database/table.json?_shape=objects \n                     Also introduced a new  _shape  called  object  which looks like this: \n                     /database/table.json?_shape=object \n                     Returning an object for the rows key: \n                     ...\n\"rows\": {\n    \"pk1\": {\n        ...\n    },\n    \"pk2\": {\n        ...\n    }\n} \n                     Refs  #122 \n                 \n                 \n                     Utility for writing test database fixtures to a .db file \n                     python tests/fixtures.py /tmp/hello.db \n                     This is useful for making a SQLite database of the test fixtures for\n                        interactive exploration. \n                 \n                 \n                     Compound primary key  _next=  now plays well with extra filters \n                     Closes  #190 \n                 \n                 \n                     Fixed bug with keyset pagination over compound primary keys \n                     Refs  #190 \n                 \n                 \n                     Database/Table views inherit  source/license/source_url/license_url \n                        metadata \n                     If you set the  source_url/license_url/source/license  fields in your root\n                        metadata those values will now be inherited all the way down to the database\n                        and table templates. \n                     The  title/description  are NOT inherited. \n                     Also added unit tests for the HTML generated by the metadata. \n                     Refs  #185 \n                 \n                 \n                     Add metadata, if it exists, to heroku temp dir ( #178 ) [Tony Hirst] \n                 \n                 \n                     Initial documentation for pagination \n                 \n                 \n                     Broke up test_app into test_api and test_html \n                 \n                 \n                     Fixed bug with .json path regular expression \n                     I had a table called  geojson  and it caused an exception because the regex\n                        was matching  .json  and not  \\.json \n                 \n                 \n                     Deploy to Heroku with Python 3.6.3", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/194\", \"label\": \"#194\"}, {\"href\": \"https://github.com/simonw/datasette/issues/189\", \"label\": \"#189\"}, {\"href\": \"https://github.com/simonw/datasette/issues/189\", \"label\": \"#189\"}, {\"href\": \"https://github.com/simonw/datasette/issues/189\", \"label\": \"#189\"}, {\"href\": \"https://github.com/simonw/datasette/issues/150\", \"label\": \"#150\"}, {\"href\": \"https://github.com/simonw/datasette/issues/180\", \"label\": \"#180\"}, {\"href\": \"https://github.com/simonw/datasette/issues/192\", \"label\": \"#192\"}, {\"href\": \"https://github.com/simonw/datasette/issues/122\", \"label\": \"#122\"}, {\"href\": \"https://github.com/simonw/datasette/issues/190\", \"label\": \"#190\"}, {\"href\": \"https://github.com/simonw/datasette/issues/190\", \"label\": \"#190\"}, {\"href\": \"https://github.com/simonw/datasette/issues/185\", \"label\": \"#185\"}, {\"href\": \"https://github.com/simonw/datasette/issues/178\", \"label\": \"#178\"}]"}, "changelog~3Aid17": {"id": "changelog:id17", "page": "changelog", "ref": "id17", "title": "0.63 (2022-10-27)", "content": "See  Datasette 0.63: The annotated release notes  for more background on the changes in this release.", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://simonwillison.net/2022/Oct/27/datasette-0-63/\", \"label\": \"Datasette 0.63: The annotated release notes\"}]"}, "changelog~3Aid176": {"id": "changelog:id176", "page": "changelog", "ref": "id176", "title": "0.14 (2017-12-09)", "content": "The theme of this release is customization: Datasette now allows every aspect\n                of its presentation  to be customized \n                either using additional CSS or by providing entirely new templates. \n             Datasette's  metadata.json format \n                has also been expanded, to allow per-database and per-table metadata. A new\n                 datasette skeleton  command can be used to generate a skeleton JSON file\n                ready to be filled in with per-database and per-table details. \n             The  metadata.json  file can also be used to define\n                 canned queries ,\n                as a more powerful alternative to SQL views. \n             \n                 \n                     extra_css_urls / extra_js_urls  in metadata \n                     A mechanism in the  metadata.json  format for adding custom CSS and JS urls. \n                     Create a  metadata.json  file that looks like this: \n                     {\n    \"extra_css_urls\": [\n        \"https://simonwillison.net/static/css/all.bf8cd891642c.css\"\n    ],\n    \"extra_js_urls\": [\n        \"https://code.jquery.com/jquery-3.2.1.slim.min.js\"\n    ]\n} \n                     Then start datasette like this: \n                     datasette mydb.db --metadata=metadata.json \n                     The CSS and JavaScript files will be linked in the  <head>  of every page. \n                     You can also specify a SRI (subresource integrity hash) for these assets: \n                     {\n    \"extra_css_urls\": [\n        {\n            \"url\": \"https://simonwillison.net/static/css/all.bf8cd891642c.css\",\n            \"sri\": \"sha384-9qIZekWUyjCyDIf2YK1FRoKiPJq4PHt6tp/ulnuuyRBvazd0hG7pWbE99zvwSznI\"\n        }\n    ],\n    \"extra_js_urls\": [\n        {\n            \"url\": \"https://code.jquery.com/jquery-3.2.1.slim.min.js\",\n            \"sri\": \"sha256-k2WSCIexGzOj3Euiig+TlR8gA0EmPjuc79OEeY5L45g=\"\n        }\n    ]\n} \n                     Modern browsers will only execute the stylesheet or JavaScript if the SRI hash\n                        matches the content served. You can generate hashes using  https://www.srihash.org/ \n                 \n                 \n                     Auto-link column values that look like URLs ( #153 ) \n                 \n                 \n                     CSS styling hooks as classes on the body ( #153 ) \n                     Every template now gets CSS classes in the body designed to support custom\n                        styling. \n                     The index template (the top level page at  / ) gets this: \n                     <body class=\"index\"> \n                     The database template ( /dbname/ ) gets this: \n                     <body class=\"db db-dbname\"> \n                     The table template ( /dbname/tablename ) gets: \n                     <body class=\"table db-dbname table-tablename\"> \n                     The row template ( /dbname/tablename/rowid ) gets: \n                     <body class=\"row db-dbname table-tablename\"> \n                     The  db-x  and  table-x  classes use the database or table names themselves IF\n                        they are valid CSS identifiers. If they aren't, we strip any invalid\n                        characters out and append a 6 character md5 digest of the original name, in\n                        order to ensure that multiple tables which resolve to the same stripped\n                        character version still have different CSS classes. \n                     Some examples (extracted from the unit tests): \n                     \"simple\" => \"simple\"\n\"MixedCase\" => \"MixedCase\"\n\"-no-leading-hyphens\" => \"no-leading-hyphens-65bea6\"\n\"_no-leading-underscores\" => \"no-leading-underscores-b921bc\"\n\"no spaces\" => \"no-spaces-7088d7\"\n\"-\" => \"336d5e\"\n\"no $ characters\" => \"no--characters-59e024\" \n                 \n                 \n                     datasette --template-dir=mytemplates/  argument \n                     You can now pass an additional argument specifying a directory to look for\n                        custom templates in. \n                     Datasette will fall back on the default templates if a template is not\n                        found in that directory. \n                 \n                 \n                     Ability to over-ride templates for individual tables/databases. \n                     It is now possible to over-ride templates on a per-database / per-row or per-\n                        table basis. \n                     When you access e.g.  /mydatabase/mytable  Datasette will look for the following: \n                     - table-mydatabase-mytable.html\n- table.html \n                     If you provided a  --template-dir  argument to datasette serve it will look in\n                        that directory first. \n                     The lookup rules are as follows: \n                     Index page (/):\n    index.html\n\nDatabase page (/mydatabase):\n    database-mydatabase.html\n    database.html\n\nTable page (/mydatabase/mytable):\n    table-mydatabase-mytable.html\n    table.html\n\nRow page (/mydatabase/mytable/id):\n    row-mydatabase-mytable.html\n    row.html \n                     If a table name has spaces or other unexpected characters in it, the template\n                        filename will follow the same rules as our custom  <body>  CSS classes\n                        - for example, a table called \"Food Trucks\"\n                        will attempt to load the following templates: \n                     table-mydatabase-Food-Trucks-399138.html\ntable.html \n                     It is possible to extend the default templates using Jinja template\n                        inheritance. If you want to customize EVERY row template with some additional\n                        content you can do so by creating a row.html template like this: \n                     {% extends \"default:row.html\" %}\n\n{% block content %}\n<h1>EXTRA HTML AT THE TOP OF THE CONTENT BLOCK</h1>\n<p>This line renders the original block:</p>\n{{ super() }}\n{% endblock %} \n                 \n                 \n                     --static  option for datasette serve ( #160 ) \n                     You can now tell Datasette to serve static files from a specific location at a\n                        specific mountpoint. \n                     For example: \n                     datasette serve mydb.db --static extra-css:/tmp/static/css \n                     Now if you visit this URL: \n                     http://localhost:8001/extra-css/blah.css \n                     The following file will be served: \n                     /tmp/static/css/blah.css \n                 \n                 \n                     Canned query support. \n                     Named canned queries can now be defined in  metadata.json  like this: \n                     {\n    \"databases\": {\n        \"timezones\": {\n            \"queries\": {\n                \"timezone_for_point\": \"select tzid from timezones ...\"\n            }\n        }\n    }\n} \n                     These will be shown in a new \"Queries\" section beneath \"Views\" on the database page. \n                 \n                 \n                     New  datasette skeleton  command for generating  metadata.json  ( #164 ) \n                 \n                 \n                     metadata.json  support for per-table/per-database metadata ( #165 ) \n                     Also added support for descriptions and HTML descriptions. \n                     Here's an example metadata.json file illustrating custom per-database and per-\n                        table metadata: \n                     {\n    \"title\": \"Overall datasette title\",\n    \"description_html\": \"This is a <em>description with HTML</em>.\",\n    \"databases\": {\n        \"db1\": {\n            \"title\": \"First database\",\n            \"description\": \"This is a string description & has no HTML\",\n            \"license_url\": \"http://example.com/\",\n        \"license\": \"The example license\",\n            \"queries\": {\n              \"canned_query\": \"select * from table1 limit 3;\"\n            },\n            \"tables\": {\n                \"table1\": {\n                    \"title\": \"Custom title for table1\",\n                    \"description\": \"Tables can have descriptions too\",\n                    \"source\": \"This has a custom source\",\n                    \"source_url\": \"http://example.com/\"\n                }\n            }\n        }\n    }\n} \n                 \n                 \n                     Renamed  datasette build  command to  datasette inspect  ( #130 ) \n                 \n                 \n                     Upgrade to Sanic 0.7.0 ( #168 ) \n                     https://github.com/channelcat/sanic/releases/tag/0.7.0 \n                 \n                 \n                     Package and publish commands now accept  --static  and  --template-dir \n                     Example usage: \n                     datasette package --static css:extra-css/ --static js:extra-js/ \\\n  sf-trees.db --template-dir templates/ --tag sf-trees --branch master \n                     This creates a local Docker image that includes copies of the templates/,\n                        extra-css/ and extra-js/ directories. You can then run it like this: \n                     docker run -p 8001:8001 sf-trees \n                     For publishing to Zeit now: \n                     datasette publish now --static css:extra-css/ --static js:extra-js/ \\\n  sf-trees.db --template-dir templates/ --name sf-trees --branch master \n                 \n                 \n                     HTML comment showing which templates were considered for a page ( #171 )", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://docs.datasette.io/en/stable/custom_templates.html\", \"label\": \"to be customized\"}, {\"href\": \"https://docs.datasette.io/en/stable/metadata.html\", \"label\": \"metadata.json format\"}, {\"href\": \"https://docs.datasette.io/en/stable/sql_queries.html#canned-queries\", \"label\": \"canned queries\"}, {\"href\": \"https://www.srihash.org/\", \"label\": \"https://www.srihash.org/\"}, {\"href\": \"https://github.com/simonw/datasette/issues/153\", \"label\": \"#153\"}, {\"href\": \"https://github.com/simonw/datasette/issues/153\", \"label\": \"#153\"}, {\"href\": \"https://github.com/simonw/datasette/issues/160\", \"label\": \"#160\"}, {\"href\": \"https://github.com/simonw/datasette/issues/164\", \"label\": \"#164\"}, {\"href\": \"https://github.com/simonw/datasette/issues/165\", \"label\": \"#165\"}, {\"href\": \"https://github.com/simonw/datasette/issues/130\", \"label\": \"#130\"}, {\"href\": \"https://github.com/simonw/datasette/issues/168\", \"label\": \"#168\"}, {\"href\": \"https://github.com/channelcat/sanic/releases/tag/0.7.0\", \"label\": \"https://github.com/channelcat/sanic/releases/tag/0.7.0\"}, {\"href\": \"https://github.com/simonw/datasette/issues/171\", \"label\": \"#171\"}]"}, "changelog~3Aid18": {"id": "changelog:id18", "page": "changelog", "ref": "id18", "title": "0.62 (2022-08-14)", "content": "Datasette can now run entirely in your browser using WebAssembly. Try out  Datasette Lite , take a look  at the code  or read more about it in  Datasette Lite: a server-side Python web application running in a browser . \n             Datasette now has a  Discord community  for questions and discussions about Datasette and its ecosystem of projects.", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://lite.datasette.io/\", \"label\": \"Datasette Lite\"}, {\"href\": \"https://github.com/simonw/datasette-lite\", \"label\": \"at the code\"}, {\"href\": \"https://simonwillison.net/2022/May/4/datasette-lite/\", \"label\": \"Datasette Lite: a server-side Python web application running in a browser\"}, {\"href\": \"https://discord.gg/ktd74dm5mw\", \"label\": \"Discord community\"}]"}, "changelog~3Aid185": {"id": "changelog:id185", "page": "changelog", "ref": "id185", "title": "0.13 (2017-11-24)", "content": "Search now applies to current filters. \n                     Combined search into the same form as filters. \n                     Closes  #133 \n                 \n                 \n                     Much tidier design for table view header. \n                     Closes  #147 \n                 \n                 \n                     Added  ?column__not=blah  filter. \n                     Closes  #148 \n                 \n                 \n                     Row page now resolves foreign keys. \n                     Closes  #132 \n                 \n                 \n                     Further tweaks to select/input filter styling. \n                     Refs  #86  - thanks for the help, @natbat! \n                 \n                 \n                     Show linked foreign key in table cells. \n                 \n                 \n                     Added UI for editing table filters. \n                     Refs  #86 \n                 \n                 \n                     Hide FTS-created tables on index pages. \n                     Closes  #129 \n                 \n                 \n                     Add publish to heroku support [Jacob Kaplan-Moss] \n                     datasette publish heroku mydb.db \n                     Pull request  #104 \n                 \n                 \n                     Initial implementation of  ?_group_count=column . \n                     URL shortcut for counting rows grouped by one or more columns. \n                     ?_group_count=column1&_group_count=column2  works as well. \n                     SQL generated looks like this: \n                     select \"qSpecies\", count(*) as \"count\"\nfrom Street_Tree_List\ngroup by \"qSpecies\"\norder by \"count\" desc limit 100 \n                     Or for two columns like this: \n                     select \"qSpecies\", \"qSiteInfo\", count(*) as \"count\"\nfrom Street_Tree_List\ngroup by \"qSpecies\", \"qSiteInfo\"\norder by \"count\" desc limit 100 \n                     Refs  #44 \n                 \n                 \n                     Added  --build=master  option to datasette publish and package. \n                     The  datasette publish  and  datasette package  commands both now accept an\n                        optional  --build  argument. If provided, this can be used to specify a branch\n                        published to GitHub that should be built into the container. \n                     This makes it easier to test code that has not yet been officially released to\n                        PyPI, e.g.: \n                     datasette publish now mydb.db --branch=master \n                 \n                 \n                     Implemented  ?_search=XXX  + UI if a FTS table is detected. \n                     Closes  #131 \n                 \n                 \n                     Added  datasette --version  support. \n                 \n                 \n                     Table views now show expanded foreign key references, if possible. \n                     If a table has foreign key columns, and those foreign key tables have\n                         label_columns , the TableView will now query those other tables for the\n                        corresponding values and display those values as links in the corresponding\n                        table cells. \n                     label_columns are currently detected by the  inspect()  function, which looks\n                        for any table that has just two columns - an ID column and one other - and\n                        sets the  label_column  to be that second non-ID column. \n                 \n                 \n                     Don't prevent tabbing to \"Run SQL\" button ( #117 ) [Robert Gieseke] \n                     See comment in  #115 \n                 \n                 \n                     Add keyboard shortcut to execute SQL query ( #115 ) [Robert Gieseke] \n                 \n                 \n                     Allow  --load-extension  to be set via environment variable. \n                 \n                 \n                     Add support for  ?field__isnull=1  ( #107 ) [Ray N] \n                 \n                 \n                     Add spatialite, switch to debian and local build ( #114 ) [Ariel N\u00fa\u00f1ez] \n                 \n                 \n                     Added  --load-extension  argument to datasette serve. \n                     Allows loading of SQLite extensions. Refs  #110 .", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/133\", \"label\": \"#133\"}, {\"href\": \"https://github.com/simonw/datasette/issues/147\", \"label\": \"#147\"}, {\"href\": \"https://github.com/simonw/datasette/issues/148\", \"label\": \"#148\"}, {\"href\": \"https://github.com/simonw/datasette/issues/132\", \"label\": \"#132\"}, {\"href\": \"https://github.com/simonw/datasette/issues/86\", \"label\": \"#86\"}, {\"href\": \"https://github.com/simonw/datasette/issues/86\", \"label\": \"#86\"}, {\"href\": \"https://github.com/simonw/datasette/issues/129\", \"label\": \"#129\"}, {\"href\": \"https://github.com/simonw/datasette/issues/104\", \"label\": \"#104\"}, {\"href\": \"https://github.com/simonw/datasette/issues/44\", \"label\": \"#44\"}, {\"href\": \"https://github.com/simonw/datasette/issues/131\", \"label\": \"#131\"}, {\"href\": \"https://github.com/simonw/datasette/issues/117\", \"label\": \"#117\"}, {\"href\": \"https://github.com/simonw/datasette/issues/115\", \"label\": \"#115\"}, {\"href\": \"https://github.com/simonw/datasette/issues/115\", \"label\": \"#115\"}, {\"href\": \"https://github.com/simonw/datasette/issues/107\", \"label\": \"#107\"}, {\"href\": \"https://github.com/simonw/datasette/issues/114\", \"label\": \"#114\"}, {\"href\": \"https://github.com/simonw/datasette/issues/110\", \"label\": \"#110\"}]"}, "changelog~3Aid19": {"id": "changelog:id19", "page": "changelog", "ref": "id19", "title": "Features", "content": "Datasette is now compatible with  Pyodide .  This is the enabling technology behind  Datasette Lite . ( #1733 ) \n                     \n                     \n                         Database file downloads now implement conditional GET using ETags. ( #1739 ) \n                     \n                     \n                         HTML for facet results and suggested results has been extracted out into new templates  _facet_results.html  and  _suggested_facets.html . Thanks, M. Nasimul Haque. ( #1759 ) \n                     \n                     \n                         Datasette now runs some SQL queries in parallel. This has limited impact on performance, see  this research issue  for details. \n                     \n                     \n                         New  --nolock  option for ignoring file locks when opening read-only databases. ( #1744 ) \n                     \n                     \n                         Spaces in the database names in URLs are now encoded as  +  rather than  ~20 . ( #1701 ) \n                     \n                     \n                         <Binary: 2427344 bytes>  is now displayed as  <Binary: 2,427,344 bytes>  and is accompanied by tooltip showing \"2.3MB\". ( #1712 ) \n                     \n                     \n                         The base Docker image used by  datasette publish cloudrun ,  datasette package  and the  official Datasette image  has been upgraded to  3.10.6-slim-bullseye .  ( #1768 ) \n                     \n                     \n                         Canned writable queries against immutable databases now show a warning message. ( #1728 ) \n                     \n                     \n                         datasette publish cloudrun  has a new  --timeout  option which can be used to increase the time limit applied by the Google Cloud build environment. Thanks, Tim Sherratt. ( #1717 ) \n                     \n                     \n                         datasette publish cloudrun  has new  --min-instances  and  --max-instances  options. ( #1779 )", "breadcrumbs": "[\"Changelog\", \"0.62 (2022-08-14)\"]", "references": "[{\"href\": \"https://pyodide.org/\", \"label\": \"Pyodide\"}, {\"href\": \"https://lite.datasette.io/\", \"label\": \"Datasette Lite\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1733\", \"label\": \"#1733\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1739\", \"label\": \"#1739\"}, {\"href\": \"https://github.com/simonw/datasette/pull/1759\", \"label\": \"#1759\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1727\", \"label\": \"this research issue\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1744\", \"label\": \"#1744\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1701\", \"label\": \"#1701\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1712\", \"label\": \"#1712\"}, {\"href\": \"https://hub.docker.com/datasetteproject/datasette\", \"label\": \"official Datasette image\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1768\", \"label\": \"#1768\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1728\", \"label\": \"#1728\"}, {\"href\": \"https://github.com/simonw/datasette/pull/1717\", \"label\": \"#1717\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1779\", \"label\": \"#1779\"}]"}, "changelog~3Aid2": {"id": "changelog:id2", "page": "changelog", "ref": "id2", "title": "0.65.2 (2025-11-05)", "content": "Fixes an  open redirect  security issue: Datasette instances would redirect to  example.com/foo/bar  if you accessed the path  //example.com/foo/bar . Thanks to  James Jefferies  for the fix. ( #2429 ) \n                 \n                 \n                     Upgraded for compatibility with Python 3.14. \n                 \n                 \n                     Fixed  datasette publish cloudrun  to work with changes to the underlying Cloud Run architecture. ( #2511 ) \n                 \n                 \n                     Minor upgrades to fix warnings, including  pkg_resources  deprecation.", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/jamesjefferies\", \"label\": \"James Jefferies\"}, {\"href\": \"https://github.com/simonw/datasette/issues/2429\", \"label\": \"#2429\"}, {\"href\": \"https://github.com/simonw/datasette/issues/2511\", \"label\": \"#2511\"}]"}, "changelog~3Aid20": {"id": "changelog:id20", "page": "changelog", "ref": "id20", "title": "Documentation", "content": "Examples in the documentation now include a copy-to-clipboard button. ( #1748 ) \n                     \n                     \n                         Documentation now uses the  Furo  Sphinx theme. ( #1746 ) \n                     \n                     \n                         Code examples in the documentation are now all formatted using Black. ( #1718 ) \n                     \n                     \n                         Request.fake()  method is now documented, see  Request object . \n                     \n                     \n                         New documentation for plugin authors:  Registering a plugin for the duration of a test . ( #903 )", "breadcrumbs": "[\"Changelog\", \"0.62 (2022-08-14)\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/1748\", \"label\": \"#1748\"}, {\"href\": \"https://github.com/pradyunsg/furo\", \"label\": \"Furo\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1746\", \"label\": \"#1746\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1718\", \"label\": \"#1718\"}, {\"href\": \"https://github.com/simonw/datasette/issues/903\", \"label\": \"#903\"}]"}, "changelog~3Aid200": {"id": "changelog:id200", "page": "changelog", "ref": "id200", "title": "0.12 (2017-11-16)", "content": "Added  __version__ , now displayed as tooltip in page footer ( #108 ). \n                 \n                 \n                     Added initial docs, including a changelog ( #99 ). \n                 \n                 \n                     Turned on auto-escaping in Jinja. \n                 \n                 \n                     Added a UI for editing named parameters ( #96 ). \n                     You can now construct a custom SQL statement using SQLite named\n                        parameters (e.g.  :name ) and datasette will display form fields for\n                        editing those parameters.  Here\u2019s an example  which lets you see the\n                        most popular names for dogs of different species registered through\n                        various dog registration schemes in Australia. \n                 \n             \n             \n             \n                 \n                     Pin to specific Jinja version. ( #100 ). \n                 \n                 \n                     Default to 127.0.0.1 not 0.0.0.0. ( #98 ). \n                 \n                 \n                     Added extra metadata options to publish and package commands. ( #92 ). \n                     You can now run these commands like so: \n                     datasette now publish mydb.db \\\n    --title=\"My Title\" \\\n    --source=\"Source\" \\\n    --source_url=\"http://www.example.com/\" \\\n    --license=\"CC0\" \\\n    --license_url=\"https://creativecommons.org/publicdomain/zero/1.0/\" \n                     This will write those values into the metadata.json that is packaged with the\n                        app. If you also pass  --metadata=metadata.json  that file will be updated with the extra\n                        values before being written into the Docker image. \n                 \n                 \n                     Added production-ready Dockerfile ( #94 ) [Andrew\n                        Cutler] \n                 \n                 \n                     New  ?_sql_time_limit_ms=10  argument to database and table page ( #95 ) \n                 \n                 \n                     SQL syntax highlighting with Codemirror ( #89 ) [Tom Dyson]", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/108\", \"label\": \"#108\"}, {\"href\": \"https://github.com/simonw/datasette/issues/99\", \"label\": \"#99\"}, {\"href\": \"https://github.com/simonw/datasette/issues/96\", \"label\": \"#96\"}, {\"href\": \"https://australian-dogs.now.sh/australian-dogs-3ba9628?sql=select+name%2C+count%28*%29+as+n+from+%28%0D%0A%0D%0Aselect+upper%28%22Animal+name%22%29+as+name+from+%5BAdelaide-City-Council-dog-registrations-2013%5D+where+Breed+like+%3Abreed%0D%0A%0D%0Aunion+all%0D%0A%0D%0Aselect+upper%28Animal_Name%29+as+name+from+%5BAdelaide-City-Council-dog-registrations-2014%5D+where+Breed_Description+like+%3Abreed%0D%0A%0D%0Aunion+all+%0D%0A%0D%0Aselect+upper%28Animal_Name%29+as+name+from+%5BAdelaide-City-Council-dog-registrations-2015%5D+where+Breed_Description+like+%3Abreed%0D%0A%0D%0Aunion+all%0D%0A%0D%0Aselect+upper%28%22AnimalName%22%29+as+name+from+%5BCity-of-Port-Adelaide-Enfield-Dog_Registrations_2016%5D+where+AnimalBreed+like+%3Abreed%0D%0A%0D%0Aunion+all%0D%0A%0D%0Aselect+upper%28%22Animal+Name%22%29+as+name+from+%5BMitcham-dog-registrations-2015%5D+where+Breed+like+%3Abreed%0D%0A%0D%0Aunion+all%0D%0A%0D%0Aselect+upper%28%22DOG_NAME%22%29+as+name+from+%5Bburnside-dog-registrations-2015%5D+where+DOG_BREED+like+%3Abreed%0D%0A%0D%0Aunion+all+%0D%0A%0D%0Aselect+upper%28%22Animal_Name%22%29+as+name+from+%5Bcity-of-playford-2015-dog-registration%5D+where+Breed_Description+like+%3Abreed%0D%0A%0D%0Aunion+all%0D%0A%0D%0Aselect+upper%28%22Animal+Name%22%29+as+name+from+%5Bcity-of-prospect-dog-registration-details-2016%5D+where%22Breed+Description%22+like+%3Abreed%0D%0A%0D%0A%29+group+by+name+order+by+n+desc%3B&breed=pug\", \"label\": \"Here\u2019s an example\"}, {\"href\": \"https://github.com/simonw/datasette/issues/100\", \"label\": \"#100\"}, {\"href\": \"https://github.com/simonw/datasette/issues/98\", \"label\": \"#98\"}, {\"href\": \"https://github.com/simonw/datasette/issues/92\", \"label\": \"#92\"}, {\"href\": \"https://github.com/simonw/datasette/issues/94\", \"label\": \"#94\"}, {\"href\": \"https://github.com/simonw/datasette/issues/95\", \"label\": \"#95\"}, {\"href\": \"https://github.com/simonw/datasette/issues/89\", \"label\": \"#89\"}]"}, "changelog~3Aid21": {"id": "changelog:id21", "page": "changelog", "ref": "id21", "title": "0.61.1 (2022-03-23)", "content": "Fixed a bug where databases with a different route from their name (as used by the  datasette-hashed-urls plugin ) returned errors when executing custom SQL queries. ( #1682 )", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://datasette.io/plugins/datasette-hashed-urls\", \"label\": \"datasette-hashed-urls plugin\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1682\", \"label\": \"#1682\"}]"}, "changelog~3Aid210": {"id": "changelog:id210", "page": "changelog", "ref": "id210", "title": "0.11 (2017-11-14)", "content": "Added  datasette publish now --force  option. \n                     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. \n                 \n                 \n                     Enable  --cors  by default when running in a container.", "breadcrumbs": "[\"Changelog\"]", "references": "[]"}, "changelog~3Aid211": {"id": "changelog:id211", "page": "changelog", "ref": "id211", "title": "0.10 (2017-11-14)", "content": "Fixed  #83  - 500 error on individual row pages. \n                 \n                 \n                     Stop using sqlite WITH RECURSIVE in our tests. \n                     The version of Python 3 running in Travis CI doesn't support this.", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/83\", \"label\": \"#83\"}]"}, "changelog~3Aid213": {"id": "changelog:id213", "page": "changelog", "ref": "id213", "title": "0.9 (2017-11-13)", "content": "Added  --sql_time_limit_ms  and  --extra-options . \n                     The serve command now accepts  --sql_time_limit_ms  for customizing the SQL time\n                        limit. \n                     The publish and package commands now accept  --extra-options  which can be used\n                        to specify additional options to be passed to the datasite serve command when\n                        it executes inside the resulting Docker containers.", "breadcrumbs": "[\"Changelog\"]", "references": "[]"}, "changelog~3Aid214": {"id": "changelog:id214", "page": "changelog", "ref": "id214", "title": "0.8 (2017-11-13)", "content": "V0.8 - added PyPI metadata, ready to ship. \n                 \n                 \n                     Implemented offset/limit pagination for views ( #70 ). \n                 \n                 \n                     Improved pagination. ( #78 ) \n                 \n                 \n                     Limit on max rows returned, controlled by  --max_returned_rows  option. ( #69 ) \n                     If someone executes 'select * from table' against a table with a million rows\n                        in it, we could run into problems: just serializing that much data as JSON is\n                        likely to lock up the server. \n                     Solution: we now have a hard limit on the maximum number of rows that can be\n                        returned by a query. If that limit is exceeded, the server will return a\n                         \"truncated\": true  field in the JSON. \n                     This limit can be optionally controlled by the new  --max_returned_rows \n                        option. Setting that option to 0 disables the limit entirely.", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/70\", \"label\": \"#70\"}, {\"href\": \"https://github.com/simonw/datasette/issues/78\", \"label\": \"#78\"}, {\"href\": \"https://github.com/simonw/datasette/issues/69\", \"label\": \"#69\"}]"}, "changelog~3Aid22": {"id": "changelog:id22", "page": "changelog", "ref": "id22", "title": "0.61 (2022-03-23)", "content": "In preparation for Datasette 1.0, this release includes two potentially backwards-incompatible changes. Hashed URL mode has been moved to a separate plugin, and the way Datasette generates URLs to databases and tables with special characters in their name such as  /  and  .  has changed. \n             Datasette also now requires Python 3.7 or higher. \n             \n                 \n                     URLs within Datasette now use a different encoding scheme for tables or databases that include \"special\" characters outside of the range of  a-zA-Z0-9_- . This scheme is explained here:  Tilde encoding . ( #1657 ) \n                 \n                 \n                     Removed hashed URL mode from Datasette. The new  datasette-hashed-urls  plugin can be used to achieve the same result, see  datasette-hashed-urls  for details. ( #1661 ) \n                 \n                 \n                     Databases can now have a custom path within the Datasette instance that is independent of the database name, using the  db.route  property. ( #1668 ) \n                 \n                 \n                     Datasette is now covered by a  Code of Conduct . ( #1654 ) \n                 \n                 \n                     Python 3.6 is no longer supported. ( #1577 ) \n                 \n                 \n                     Tests now run against Python 3.11-dev. ( #1621 ) \n                 \n                 \n                     New  datasette.ensure_permissions(actor, permissions)  internal method for checking multiple permissions at once. ( #1675 ) \n                 \n                 \n                     New  datasette.check_visibility(actor, action, resource=None)  internal method for checking if a user can see a resource that would otherwise be invisible to unauthenticated users. ( #1678 ) \n                 \n                 \n                     Table and row HTML pages now include a  <link rel=\"alternate\" type=\"application/json+datasette\" href=\"...\">  element and return a  Link: URL; rel=\"alternate\"; type=\"application/json+datasette\"  HTTP header pointing to the JSON version of those pages. ( #1533 ) \n                 \n                 \n                     Access-Control-Expose-Headers: Link  is now added to the CORS headers, allowing remote JavaScript to access that header. \n                 \n                 \n                     Canned queries are now shown at the top of the database page, directly below the SQL editor. Previously they were shown at the bottom, below the list of tables. ( #1612 ) \n                 \n                 \n                     Datasette now has a default favicon. ( #1603 ) \n                 \n                 \n                     sqlite_stat  tables are now hidden by default. ( #1587 ) \n                 \n                 \n                     SpatiaLite tables  data_licenses ,  KNN  and  KNN2  are now hidden by default. ( #1601 ) \n                 \n                 \n                     SQL query tracing mechanism now works for queries executed in  asyncio  sub-tasks, such as those created by  asyncio.gather() . ( #1576 ) \n                 \n                 \n                     datasette.tracer  mechanism is now documented. \n                 \n                 \n                     Common Datasette symbols can now be imported directly from the top-level  datasette  package, see  Import shortcuts . Those symbols are  Response ,  Forbidden ,  NotFound ,  hookimpl ,  actor_matches_allow . ( #957 ) \n                 \n                 \n                     /-/versions  page now returns additional details for libraries used by SpatiaLite. ( #1607 ) \n                 \n                 \n                     Documentation now links to the  Datasette Tutorials . \n                 \n                 \n                     Datasette will now also look for SpatiaLite in  /opt/homebrew  - thanks, Dan Peterson. ( #1649 ) \n                 \n                 \n                     Fixed bug where  custom pages  did not work on Windows. Thanks, Robert Christie. ( #1545 ) \n                 \n                 \n                     Fixed error caused when a table had a column named  n . ( #1228 )", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/1657\", \"label\": \"#1657\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1661\", \"label\": \"#1661\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1668\", \"label\": \"#1668\"}, {\"href\": \"https://github.com/simonw/datasette/blob/main/CODE_OF_CONDUCT.md\", \"label\": \"Code of Conduct\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1654\", \"label\": \"#1654\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1577\", \"label\": \"#1577\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1621\", \"label\": \"#1621\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1675\", \"label\": \"#1675\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1678\", \"label\": \"#1678\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1533\", \"label\": \"#1533\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1612\", \"label\": \"#1612\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1603\", \"label\": \"#1603\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1587\", \"label\": \"#1587\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1601\", \"label\": \"#1601\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1576\", \"label\": \"#1576\"}, {\"href\": \"https://github.com/simonw/datasette/issues/957\", \"label\": \"#957\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1607\", \"label\": \"#1607\"}, {\"href\": \"https://datasette.io/tutorials\", \"label\": \"Datasette Tutorials\"}, {\"href\": \"https://github.com/simonw/datasette/pull/1649\", \"label\": \"#1649\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1545\", \"label\": \"#1545\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1228\", \"label\": \"#1228\"}]"}, "changelog~3Aid23": {"id": "changelog:id23", "page": "changelog", "ref": "id23", "title": "0.60.2 (2022-02-07)", "content": "Fixed a bug where Datasette would open the same file twice with two different database names if you ran  datasette file.db file.db . ( #1632 )", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/1632\", \"label\": \"#1632\"}]"}, "changelog~3Aid24": {"id": "changelog:id24", "page": "changelog", "ref": "id24", "title": "0.60.1 (2022-01-20)", "content": "Fixed a bug where installation on Python 3.6 stopped working due to a change to an underlying dependency. This release can now be installed on Python 3.6, but is the last release of Datasette that will support anything less than Python 3.7. ( #1609 )", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/1609\", \"label\": \"#1609\"}]"}, "changelog~3Aid25": {"id": "changelog:id25", "page": "changelog", "ref": "id25", "title": "0.60 (2022-01-13)", "content": "", "breadcrumbs": "[\"Changelog\"]", "references": "[]"}, "changelog~3Aid26": {"id": "changelog:id26", "page": "changelog", "ref": "id26", "title": "0.59.4 (2021-11-29)", "content": "Fixed bug where columns with a leading underscore could not be removed from the interactive filters list. ( #1527 ) \n                 \n                 \n                     Fixed bug where columns with a leading underscore were not correctly linked to by the \"Links from other tables\" interface on the row page. ( #1525 ) \n                 \n                 \n                     Upgraded dependencies  aiofiles ,  black  and  janus .", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/1527\", \"label\": \"#1527\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1525\", \"label\": \"#1525\"}]"}, "changelog~3Aid27": {"id": "changelog:id27", "page": "changelog", "ref": "id27", "title": "0.59.3 (2021-11-20)", "content": "Fixed numerous bugs when running Datasette  behind a proxy  with a prefix URL path using the  base_url  setting. A live demo of this mode is now available at  datasette-apache-proxy-demo.datasette.io/prefix/ . ( #1519 ,  #838 ) \n                 \n                 \n                     ?column__arraycontains=  and  ?column__arraynotcontains=  table parameters now also work against SQL views. ( #448 ) \n                 \n                 \n                     ?_facet_array=column  no longer returns incorrect counts if columns contain the same value more than once.", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://datasette-apache-proxy-demo.datasette.io/prefix/\", \"label\": \"datasette-apache-proxy-demo.datasette.io/prefix/\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1519\", \"label\": \"#1519\"}, {\"href\": \"https://github.com/simonw/datasette/issues/838\", \"label\": \"#838\"}, {\"href\": \"https://github.com/simonw/datasette/issues/448\", \"label\": \"#448\"}]"}, "changelog~3Aid28": {"id": "changelog:id28", "page": "changelog", "ref": "id28", "title": "0.59.2 (2021-11-13)", "content": "Column names with a leading underscore now work correctly when used as a facet. ( #1506 ) \n                 \n                 \n                     Applying  ?_nocol=  to a column no longer removes that column from the filtering interface. ( #1503 ) \n                 \n                 \n                     Official Datasette Docker container now uses Debian Bullseye as the base image. ( #1497 ) \n                 \n                 \n                     Datasette is four years old today! Here's the  original release announcement  from 2017.", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/1506\", \"label\": \"#1506\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1503\", \"label\": \"#1503\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1497\", \"label\": \"#1497\"}, {\"href\": \"https://simonwillison.net/2017/Nov/13/datasette/\", \"label\": \"original release announcement\"}]"}, "changelog~3Aid29": {"id": "changelog:id29", "page": "changelog", "ref": "id29", "title": "0.59.1 (2021-10-24)", "content": "Fix compatibility with Python 3.10. ( #1482 ) \n                 \n                 \n                     Documentation on how to use  Named parameters  with integer and floating point values. ( #1496 )", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/1482\", \"label\": \"#1482\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1496\", \"label\": \"#1496\"}]"}, "changelog~3Aid3": {"id": "changelog:id3", "page": "changelog", "ref": "id3", "title": "0.65.1 (2024-12-28)", "content": "Fixed bug with upgraded HTTPX 0.28.0 dependency. ( #2443 )", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/2443\", \"label\": \"#2443\"}]"}, "changelog~3Aid30": {"id": "changelog:id30", "page": "changelog", "ref": "id30", "title": "0.59 (2021-10-14)", "content": "Columns can now have associated metadata descriptions in  metadata.json , see  Column descriptions . ( #942 ) \n                 \n                 \n                     New  register_commands()  plugin hook allows plugins to register additional Datasette CLI commands, e.g.  datasette mycommand file.db . ( #1449 ) \n                 \n                 \n                     Adding  ?_facet_size=max  to a table page now shows the number of unique values in each facet. ( #1423 ) \n                 \n                 \n                     Upgraded dependency  httpx 0.20  - the undocumented  allow_redirects=  parameter to  datasette.client  is now  follow_redirects= , and defaults to  False  where it previously defaulted to  True . ( #1488 ) \n                 \n                 \n                     The  --cors  option now causes Datasette to return the  Access-Control-Allow-Headers: Authorization  header, in addition to  Access-Control-Allow-Origin: * . ( #1467 ) \n                 \n                 \n                     Code that figures out which named parameters a SQL query takes in order to display form fields for them is no longer confused by strings that contain colon characters. ( #1421 ) \n                 \n                 \n                     Renamed  --help-config  option to  --help-settings . ( #1431 ) \n                 \n                 \n                     datasette.databases  property is now a documented API. ( #1443 ) \n                 \n                 \n                     The  base.html  template now wraps everything other than the  <footer>  in a  <div class=\"not-footer\">  element, to help with advanced CSS customization. ( #1446 ) \n                 \n                 \n                     The  render_cell()  plugin hook can now return an awaitable function. This means the hook can execute SQL queries. ( #1425 ) \n                 \n                 \n                     register_routes(datasette)  plugin hook now accepts an optional  datasette  argument. ( #1404 ) \n                 \n                 \n                     New  hide_sql  canned query option for defaulting to hiding the SQL query used by a canned query, see  Additional canned query options . ( #1422 ) \n                 \n                 \n                     New  --cpu  option for  datasette publish cloudrun . ( #1420 ) \n                 \n                 \n                     If  Rich  is installed in the same virtual environment as Datasette, it will be used to provide enhanced display of error tracebacks on the console. ( #1416 ) \n                 \n                 \n                     datasette.utils   parse_metadata(content)  function, used by the new  datasette-remote-metadata plugin , is now a documented API. ( #1405 ) \n                 \n                 \n                     Fixed bug where  ?_next=x&_sort=rowid  could throw an error. ( #1470 ) \n                 \n                 \n                     Column cog menu no longer shows the option to facet by a column that is already selected by the default facets in metadata. ( #1469 )", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/942\", \"label\": \"#942\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1449\", \"label\": \"#1449\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1423\", \"label\": \"#1423\"}, {\"href\": \"https://github.com/encode/httpx/releases/tag/0.20.0\", \"label\": \"httpx 0.20\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1488\", \"label\": \"#1488\"}, {\"href\": \"https://github.com/simonw/datasette/pull/1467\", \"label\": \"#1467\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1421\", \"label\": \"#1421\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1431\", \"label\": \"#1431\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1443\", \"label\": \"#1443\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1446\", \"label\": \"#1446\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1425\", \"label\": \"#1425\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1404\", \"label\": \"#1404\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1422\", \"label\": \"#1422\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1420\", \"label\": \"#1420\"}, {\"href\": \"https://github.com/willmcgugan/rich\", \"label\": \"Rich\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1416\", \"label\": \"#1416\"}, {\"href\": \"https://datasette.io/plugins/datasette-remote-metadata\", \"label\": \"datasette-remote-metadata plugin\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1405\", \"label\": \"#1405\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1470\", \"label\": \"#1470\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1469\", \"label\": \"#1469\"}]"}, "changelog~3Aid31": {"id": "changelog:id31", "page": "changelog", "ref": "id31", "title": "0.58.1 (2021-07-16)", "content": "Fix for an intermittent race condition caused by the  refresh_schemas()  internal function. ( #1231 )", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/1231\", \"label\": \"#1231\"}]"}, "changelog~3Aid32": {"id": "changelog:id32", "page": "changelog", "ref": "id32", "title": "0.58 (2021-07-14)", "content": "New  datasette --uds /tmp/datasette.sock  option for binding Datasette to a Unix domain socket, see  proxy documentation  ( #1388 ) \n                 \n                 \n                     \"searchmode\": \"raw\"  table metadata option for defaulting a table to executing SQLite full-text search syntax without first escaping it, see  Advanced SQLite search queries . ( #1389 ) \n                 \n                 \n                     New plugin hook:  get_metadata(datasette, key, database, table) , for returning custom metadata for an instance, database or table. Thanks, Brandon Roberts! ( #1384 ) \n                 \n                 \n                     New plugin hook:  skip_csrf(datasette, scope) , for opting out of CSRF protection based on the incoming request. ( #1377 ) \n                 \n                 \n                     The  menu_links() ,  table_actions()  and  database_actions()  plugin hooks all gained a new optional  request  argument providing access to the current request. ( #1371 ) \n                 \n                 \n                     Major performance improvement for Datasette faceting. ( #1394 ) \n                 \n                 \n                     Improved documentation for  Running Datasette behind a proxy  to recommend using  ProxyPreservehost On  with Apache. ( #1387 ) \n                 \n                 \n                     POST  requests to endpoints that do not support that HTTP verb now return a 405 error. \n                 \n                 \n                     db.path  can now be provided as a  pathlib.Path  object, useful when writing unit tests for plugins. Thanks, Chris Amico. ( #1365 )", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/1388\", \"label\": \"#1388\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1389\", \"label\": \"#1389\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1384\", \"label\": \"#1384\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1377\", \"label\": \"#1377\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1371\", \"label\": \"#1371\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1394\", \"label\": \"#1394\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1387\", \"label\": \"#1387\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1365\", \"label\": \"#1365\"}]"}, "changelog~3Aid33": {"id": "changelog:id33", "page": "changelog", "ref": "id33", "title": "0.57.1 (2021-06-08)", "content": "Fixed visual display glitch with global navigation menu. ( #1367 ) \n                 \n                 \n                     No longer truncates the list of table columns displayed on the  /database  page. ( #1364 )", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/1367\", \"label\": \"#1367\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1364\", \"label\": \"#1364\"}]"}, "changelog~3Aid34": {"id": "changelog:id34", "page": "changelog", "ref": "id34", "title": "0.57 (2021-06-05)", "content": "This release fixes a  reflected cross-site scripting  security hole with the  ?_trace=1  feature. You should upgrade to this version, or to Datasette 0.56.1, as soon as possible. ( #1360 ) \n             \n             In addition to the security fix, this release includes  ?_col=  and  ?_nocol=  options for controlling which columns are displayed for a table,  ?_facet_size=  for increasing the number of facet results returned, re-display of your SQL query should an error occur and numerous bug fixes.", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://owasp.org/www-community/attacks/xss/#reflected-xss-attacks\", \"label\": \"reflected cross-site scripting\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1360\", \"label\": \"#1360\"}]"}, "changelog~3Aid35": {"id": "changelog:id35", "page": "changelog", "ref": "id35", "title": "0.56.1 (2021-06-05)", "content": "This release fixes a  reflected cross-site scripting  security hole with the  ?_trace=1  feature. You should upgrade to this version, or to Datasette 0.57, as soon as possible. ( #1360 )", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://owasp.org/www-community/attacks/xss/#reflected-xss-attacks\", \"label\": \"reflected cross-site scripting\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1360\", \"label\": \"#1360\"}]"}, "changelog~3Aid36": {"id": "changelog:id36", "page": "changelog", "ref": "id36", "title": "0.56 (2021-03-28)", "content": "Documentation improvements, bug fixes and support for SpatiaLite 5. \n             \n                 \n                     The SQL editor can now be resized by dragging a handle. ( #1236 ) \n                 \n                 \n                     Fixed a bug with JSON faceting and the  __arraycontains  filter caused by tables with spaces in their names. ( #1239 ) \n                 \n                 \n                     Upgraded  httpx  dependency. ( #1005 ) \n                 \n                 \n                     JSON faceting is now suggested even if a column contains blank strings. ( #1246 ) \n                 \n                 \n                     New  datasette.add_memory_database()  method. ( #1247 ) \n                 \n                 \n                     The  Response.asgi_send()  method is now documented. ( #1266 ) \n                 \n                 \n                     The official Datasette Docker image now bundles SpatiaLite version 5. ( #1278 ) \n                 \n                 \n                     Fixed a  no such table: pragma_database_list  bug when running Datasette against SQLite versions prior to SQLite 3.16.0. ( #1276 ) \n                 \n                 \n                     HTML lists displayed in table cells are now styled correctly. Thanks, Bob Whitelock. ( #1141 ,  #1252 ) \n                 \n                 \n                     Configuration directory mode now correctly serves immutable databases that are listed in  inspect-data.json . Thanks Campbell Allen and Frankie Robertson. ( #1031 ,  #1229 )", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/1236\", \"label\": \"#1236\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1239\", \"label\": \"#1239\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1005\", \"label\": \"#1005\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1246\", \"label\": \"#1246\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1247\", \"label\": \"#1247\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1266\", \"label\": \"#1266\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1278\", \"label\": \"#1278\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1276\", \"label\": \"#1276\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1141\", \"label\": \"#1141\"}, {\"href\": \"https://github.com/simonw/datasette/pull/1252\", \"label\": \"#1252\"}, {\"href\": \"https://github.com/simonw/datasette/pull/1031\", \"label\": \"#1031\"}, {\"href\": \"https://github.com/simonw/datasette/pull/1229\", \"label\": \"#1229\"}]"}, "changelog~3Aid37": {"id": "changelog:id37", "page": "changelog", "ref": "id37", "title": "0.55 (2021-02-18)", "content": "Support for cross-database SQL queries and built-in support for serving via HTTPS. \n             \n                 \n                     The new  --crossdb  command-line option causes Datasette to attach up to ten database files to the same  /_memory  database connection. This enables cross-database SQL queries, including the ability to use joins and unions to combine data from tables that exist in different database files. See  Cross-database queries  for details. ( #283 ) \n                 \n                 \n                     --ssl-keyfile  and  --ssl-certfile  options can be used to specify a TLS certificate, allowing Datasette to serve traffic over  https://  without needing to run it behind a separate proxy. ( #1221 ) \n                 \n                 \n                     The  /:memory:  page has been renamed (and redirected) to  /_memory  for consistency with the new  /_internal  database introduced in Datasette 0.54. ( #1205 ) \n                 \n                 \n                     Added plugin testing documentation on  Using pdb for errors thrown inside Datasette . ( #1207 ) \n                 \n                 \n                     The  official Datasette Docker image  now uses Python 3.7.10, applying  the latest security fix  for that Python version. ( #1235 )", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/283\", \"label\": \"#283\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1221\", \"label\": \"#1221\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1205\", \"label\": \"#1205\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1207\", \"label\": \"#1207\"}, {\"href\": \"https://hub.docker.com/r/datasetteproject/datasette\", \"label\": \"official Datasette Docker image\"}, {\"href\": \"https://www.python.org/downloads/release/python-3710/\", \"label\": \"the latest security fix\"}, {\"href\": \"https://github.com/simonw/datasette/issues/1235\", \"label\": \"#1235\"}]"}, "changelog~3Aid38": {"id": "changelog:id38", "page": "changelog", "ref": "id38", "title": "0.54.1 (2021-02-02)", "content": "Fixed a bug where  ?_search=  and  ?_sort=  parameters were incorrectly duplicated when the filter form on the table page was re-submitted. ( #1214 )", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/1214\", \"label\": \"#1214\"}]"}, "changelog~3Aid39": {"id": "changelog:id39", "page": "changelog", "ref": "id39", "title": "0.54 (2021-01-25)", "content": "The two big new features in this release are the  _internal  SQLite in-memory database storing details of all connected databases and tables, and support for JavaScript modules in plugins and additional scripts. \n             For additional commentary on this release, see  Datasette 0.54, the annotated release notes .", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://simonwillison.net/2021/Jan/25/datasette/\", \"label\": \"Datasette 0.54, the annotated release notes\"}]"}, "changelog~3Aid4": {"id": "changelog:id4", "page": "changelog", "ref": "id4", "title": "0.65 (2024-10-07)", "content": "Upgrade for compatibility with Python 3.13 (by vendoring Pint dependency). ( #2434 ) \n                 \n                 \n                     Dropped support for Python 3.8.", "breadcrumbs": "[\"Changelog\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/2434\", \"label\": \"#2434\"}]"}}