mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
Populate docs/ from 0.65.2
This commit is contained in:
parent
ec99bb46f8
commit
264bba5db2
26 changed files with 883 additions and 5641 deletions
|
|
@ -9,99 +9,105 @@ through the Datasette user interface can also be accessed as JSON via the API.
|
|||
To access the API for a page, either click on the ``.json`` link on that page or
|
||||
edit the URL and add a ``.json`` extension to it.
|
||||
|
||||
.. _json_api_default:
|
||||
If you started Datasette with the ``--cors`` option, each JSON endpoint will be
|
||||
served with the following additional HTTP headers::
|
||||
|
||||
Default representation
|
||||
----------------------
|
||||
Access-Control-Allow-Origin: *
|
||||
Access-Control-Allow-Headers: Authorization
|
||||
Access-Control-Expose-Headers: Link
|
||||
|
||||
The default JSON representation of data from a SQLite table or custom query
|
||||
looks like this:
|
||||
This means JavaScript running on any domain will be able to make cross-origin
|
||||
requests to fetch the data.
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"ok": true,
|
||||
"rows": [
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Detroit"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Los Angeles"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Memnonia"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"name": "San Francisco"
|
||||
}
|
||||
],
|
||||
"truncated": false
|
||||
}
|
||||
|
||||
``"ok"`` is always ``true`` if an error did not occur.
|
||||
|
||||
The ``"rows"`` key is a list of objects, each one representing a row.
|
||||
|
||||
The ``"truncated"`` key lets you know if the query was truncated. This can happen if a SQL query returns more than 1,000 results (or the :ref:`setting_max_returned_rows` setting).
|
||||
|
||||
For table pages, an additional key ``"next"`` may be present. This indicates that the next page in the pagination set can be retrieved using ``?_next=VALUE``.
|
||||
If you start Datasette without the ``--cors`` option only JavaScript running on
|
||||
the same domain as Datasette will be able to access the API.
|
||||
|
||||
.. _json_api_shapes:
|
||||
|
||||
Different shapes
|
||||
----------------
|
||||
|
||||
The default JSON representation of data from a SQLite table or custom query
|
||||
looks like this::
|
||||
|
||||
{
|
||||
"database": "sf-trees",
|
||||
"table": "qSpecies",
|
||||
"columns": [
|
||||
"id",
|
||||
"value"
|
||||
],
|
||||
"rows": [
|
||||
[
|
||||
1,
|
||||
"Myoporum laetum :: Myoporum"
|
||||
],
|
||||
[
|
||||
2,
|
||||
"Metrosideros excelsa :: New Zealand Xmas Tree"
|
||||
],
|
||||
[
|
||||
3,
|
||||
"Pinus radiata :: Monterey Pine"
|
||||
]
|
||||
],
|
||||
"truncated": false,
|
||||
"next": "100",
|
||||
"next_url": "http://127.0.0.1:8001/sf-trees-02c8ef1/qSpecies.json?_next=100",
|
||||
"query_ms": 1.9571781158447266
|
||||
}
|
||||
|
||||
The ``columns`` key lists the columns that are being returned, and the ``rows``
|
||||
key then returns a list of lists, each one representing a row. The order of the
|
||||
values in each row corresponds to the columns.
|
||||
|
||||
The ``_shape`` parameter can be used to access alternative formats for the
|
||||
``rows`` key which may be more convenient for your application. There are three
|
||||
options:
|
||||
|
||||
* ``?_shape=objects`` - ``"rows"`` is a list of JSON key/value objects - the default
|
||||
* ``?_shape=arrays`` - ``"rows"`` is a list of lists, where the order of values in each list matches the order of the columns
|
||||
* ``?_shape=array`` - a JSON array of objects - effectively just the ``"rows"`` key from the default representation
|
||||
* ``?_shape=arrays`` - ``"rows"`` is the default option, shown above
|
||||
* ``?_shape=objects`` - ``"rows"`` is a list of JSON key/value objects
|
||||
* ``?_shape=array`` - an JSON array of objects
|
||||
* ``?_shape=array&_nl=on`` - a newline-separated list of JSON objects
|
||||
* ``?_shape=arrayfirst`` - a flat JSON array containing just the first value from each row
|
||||
* ``?_shape=object`` - a JSON object keyed using the primary keys of the rows
|
||||
|
||||
``_shape=arrays`` looks like this:
|
||||
|
||||
.. code-block:: json
|
||||
``_shape=objects`` looks like this::
|
||||
|
||||
{
|
||||
"ok": true,
|
||||
"next": null,
|
||||
"rows": [
|
||||
[3, "Detroit"],
|
||||
[2, "Los Angeles"],
|
||||
[4, "Memnonia"],
|
||||
[1, "San Francisco"]
|
||||
]
|
||||
"database": "sf-trees",
|
||||
...
|
||||
"rows": [
|
||||
{
|
||||
"id": 1,
|
||||
"value": "Myoporum laetum :: Myoporum"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"value": "Metrosideros excelsa :: New Zealand Xmas Tree"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"value": "Pinus radiata :: Monterey Pine"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
``_shape=array`` looks like this:
|
||||
|
||||
.. code-block:: json
|
||||
``_shape=array`` looks like this::
|
||||
|
||||
[
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Detroit"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Los Angeles"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Memnonia"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"name": "San Francisco"
|
||||
}
|
||||
{
|
||||
"id": 1,
|
||||
"value": "Myoporum laetum :: Myoporum"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"value": "Metrosideros excelsa :: New Zealand Xmas Tree"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"value": "Pinus radiata :: Monterey Pine"
|
||||
}
|
||||
]
|
||||
|
||||
``_shape=array&_nl=on`` looks like this::
|
||||
|
|
@ -110,29 +116,25 @@ options:
|
|||
{"id": 2, "value": "Metrosideros excelsa :: New Zealand Xmas Tree"}
|
||||
{"id": 3, "value": "Pinus radiata :: Monterey Pine"}
|
||||
|
||||
``_shape=arrayfirst`` looks like this:
|
||||
|
||||
.. code-block:: json
|
||||
``_shape=arrayfirst`` looks like this::
|
||||
|
||||
[1, 2, 3]
|
||||
|
||||
``_shape=object`` looks like this:
|
||||
|
||||
.. code-block:: json
|
||||
``_shape=object`` looks like this::
|
||||
|
||||
{
|
||||
"1": {
|
||||
"id": 1,
|
||||
"value": "Myoporum laetum :: Myoporum"
|
||||
},
|
||||
"2": {
|
||||
"id": 2,
|
||||
"value": "Metrosideros excelsa :: New Zealand Xmas Tree"
|
||||
},
|
||||
"3": {
|
||||
"id": 3,
|
||||
"value": "Pinus radiata :: Monterey Pine"
|
||||
}
|
||||
"1": {
|
||||
"id": 1,
|
||||
"value": "Myoporum laetum :: Myoporum"
|
||||
},
|
||||
"2": {
|
||||
"id": 2,
|
||||
"value": "Metrosideros excelsa :: New Zealand Xmas Tree"
|
||||
},
|
||||
"3": {
|
||||
"id": 3,
|
||||
"value": "Pinus radiata :: Monterey Pine"
|
||||
}
|
||||
]
|
||||
|
||||
The ``object`` shape is only available for queries against tables - custom SQL
|
||||
|
|
@ -237,9 +239,6 @@ You can filter the data returned by the table based on column values using a que
|
|||
``?column__contains=value``
|
||||
Rows where the string column contains the specified value (``column like "%value%"`` in SQL).
|
||||
|
||||
``?column__notcontains=value``
|
||||
Rows where the string column does not contain the specified value (``column not like "%value%"`` in SQL).
|
||||
|
||||
``?column__endswith=value``
|
||||
Rows where the string column ends with the specified value (``column like "%value"`` in SQL).
|
||||
|
||||
|
|
@ -347,7 +346,7 @@ Special table arguments
|
|||
though this could potentially result in errors if the wrong syntax is used.
|
||||
|
||||
``?_where=SQL-fragment``
|
||||
If the :ref:`actions_execute_sql` permission is enabled, this parameter
|
||||
If the :ref:`permissions_execute_sql` permission is enabled, this parameter
|
||||
can be used to pass one or more additional SQL fragments to be used in the
|
||||
`WHERE` clause of the SQL used to query the table.
|
||||
|
||||
|
|
@ -416,9 +415,7 @@ column - you can turn that off using ``?_labels=off``.
|
|||
|
||||
You can request foreign keys be expanded in JSON using the ``_labels=on`` or
|
||||
``_label=COLUMN`` special query string parameters. Here's what an expanded row
|
||||
looks like:
|
||||
|
||||
.. code-block:: json
|
||||
looks like::
|
||||
|
||||
[
|
||||
{
|
||||
|
|
@ -457,523 +454,4 @@ You can find this near the top of the source code of those pages, looking like t
|
|||
|
||||
The JSON URL is also made available in a ``Link`` HTTP header for the page::
|
||||
|
||||
Link: <https://latest.datasette.io/fixtures/sortable.json>; rel="alternate"; type="application/json+datasette"
|
||||
|
||||
.. _json_api_cors:
|
||||
|
||||
Enabling CORS
|
||||
-------------
|
||||
|
||||
If you start Datasette with the ``--cors`` option, each JSON endpoint will be
|
||||
served with the following additional HTTP headers:
|
||||
|
||||
.. [[[cog
|
||||
from datasette.utils import add_cors_headers
|
||||
import textwrap
|
||||
headers = {}
|
||||
add_cors_headers(headers)
|
||||
output = "\n".join("{}: {}".format(k, v) for k, v in headers.items())
|
||||
cog.out("\n::\n\n")
|
||||
cog.out(textwrap.indent(output, ' '))
|
||||
cog.out("\n\n")
|
||||
.. ]]]
|
||||
|
||||
::
|
||||
|
||||
Access-Control-Allow-Origin: *
|
||||
Access-Control-Allow-Headers: Authorization, Content-Type
|
||||
Access-Control-Expose-Headers: Link
|
||||
Access-Control-Allow-Methods: GET, POST, HEAD, OPTIONS
|
||||
Access-Control-Max-Age: 3600
|
||||
|
||||
.. [[[end]]]
|
||||
|
||||
This allows JavaScript running on any domain to make cross-origin
|
||||
requests to interact with the Datasette API.
|
||||
|
||||
If you start Datasette without the ``--cors`` option only JavaScript running on
|
||||
the same domain as Datasette will be able to access the API.
|
||||
|
||||
Here's how to serve ``data.db`` with CORS enabled::
|
||||
|
||||
datasette data.db --cors
|
||||
|
||||
.. _json_api_write:
|
||||
|
||||
The JSON write API
|
||||
------------------
|
||||
|
||||
Datasette provides a write API for JSON data. This is a POST-only API that requires an authenticated API token, see :ref:`CreateTokenView`. The token will need to have the specified :ref:`authentication_permissions`.
|
||||
|
||||
.. _TableInsertView:
|
||||
|
||||
Inserting rows
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
This requires the :ref:`actions_insert_row` permission.
|
||||
|
||||
A single row can be inserted using the ``"row"`` key:
|
||||
|
||||
::
|
||||
|
||||
POST /<database>/<table>/-/insert
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer dstok_<rest-of-token>
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"row": {
|
||||
"column1": "value1",
|
||||
"column2": "value2"
|
||||
}
|
||||
}
|
||||
|
||||
If successful, this will return a ``201`` status code and the newly inserted row, for example:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"rows": [
|
||||
{
|
||||
"id": 1,
|
||||
"column1": "value1",
|
||||
"column2": "value2"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
To insert multiple rows at a time, use the same API method but send a list of dictionaries as the ``"rows"`` key:
|
||||
|
||||
::
|
||||
|
||||
POST /<database>/<table>/-/insert
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer dstok_<rest-of-token>
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"rows": [
|
||||
{
|
||||
"column1": "value1",
|
||||
"column2": "value2"
|
||||
},
|
||||
{
|
||||
"column1": "value3",
|
||||
"column2": "value4"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
If successful, this will return a ``201`` status code and a ``{"ok": true}`` response body.
|
||||
|
||||
The maximum number rows that can be submitted at once defaults to 100, but this can be changed using the :ref:`setting_max_insert_rows` setting.
|
||||
|
||||
To return the newly inserted rows, add the ``"return": true`` key to the request body:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"rows": [
|
||||
{
|
||||
"column1": "value1",
|
||||
"column2": "value2"
|
||||
},
|
||||
{
|
||||
"column1": "value3",
|
||||
"column2": "value4"
|
||||
}
|
||||
],
|
||||
"return": true
|
||||
}
|
||||
|
||||
This will return the same ``"rows"`` key as the single row example above. There is a small performance penalty for using this option.
|
||||
|
||||
If any of your rows have a primary key that is already in use, you will get an error and none of the rows will be inserted:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"ok": false,
|
||||
"errors": [
|
||||
"UNIQUE constraint failed: new_table.id"
|
||||
]
|
||||
}
|
||||
|
||||
Pass ``"ignore": true`` to ignore these errors and insert the other rows:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"rows": [
|
||||
{
|
||||
"id": 1,
|
||||
"column1": "value1",
|
||||
"column2": "value2"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"column1": "value3",
|
||||
"column2": "value4"
|
||||
}
|
||||
],
|
||||
"ignore": true
|
||||
}
|
||||
|
||||
Or you can pass ``"replace": true`` to replace any rows with conflicting primary keys with the new values. This requires the :ref:`actions_update_row` permission.
|
||||
|
||||
Pass ``"alter: true`` to automatically add any missing columns to the table. This requires the :ref:`actions_alter_table` permission.
|
||||
|
||||
.. _TableUpsertView:
|
||||
|
||||
Upserting rows
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
An upsert is an insert or update operation. If a row with a matching primary key already exists it will be updated - otherwise a new row will be inserted.
|
||||
|
||||
The upsert API is mostly the same shape as the :ref:`insert API <TableInsertView>`. It requires both the :ref:`actions_insert_row` and :ref:`actions_update_row` permissions.
|
||||
|
||||
::
|
||||
|
||||
POST /<database>/<table>/-/upsert
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer dstok_<rest-of-token>
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"rows": [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "Updated title for 1",
|
||||
"description": "Updated description for 1"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"description": "Updated description for 2",
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"title": "Item 3",
|
||||
"description": "Description for 3"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Imagine a table with a primary key of ``id`` and which already has rows with ``id`` values of ``1`` and ``2``.
|
||||
|
||||
The above example will:
|
||||
|
||||
- Update the row with ``id`` of ``1`` to set both ``title`` and ``description`` to the new values
|
||||
- Update the row with ``id`` of ``2`` to set ``title`` to the new value - ``description`` will be left unchanged
|
||||
- Insert a new row with ``id`` of ``3`` and both ``title`` and ``description`` set to the new values
|
||||
|
||||
Similar to ``/-/insert``, a ``row`` key with an object can be used instead of a ``rows`` array to upsert a single row.
|
||||
|
||||
If successful, this will return a ``200`` status code and a ``{"ok": true}`` response body.
|
||||
|
||||
Add ``"return": true`` to the request body to return full copies of the affected rows after they have been inserted or updated:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"rows": [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "Updated title for 1",
|
||||
"description": "Updated description for 1"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"description": "Updated description for 2",
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"title": "Item 3",
|
||||
"description": "Description for 3"
|
||||
}
|
||||
],
|
||||
"return": true
|
||||
}
|
||||
|
||||
This will return the following:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"ok": true,
|
||||
"rows": [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "Updated title for 1",
|
||||
"description": "Updated description for 1"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title": "Item 2",
|
||||
"description": "Updated description for 2"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"title": "Item 3",
|
||||
"description": "Description for 3"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
When using upsert you must provide the primary key column (or columns if the table has a compound primary key) for every row, or you will get a ``400`` error:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"ok": false,
|
||||
"errors": [
|
||||
"Row 0 is missing primary key column(s): \"id\""
|
||||
]
|
||||
}
|
||||
|
||||
If your table does not have an explicit primary key you should pass the SQLite ``rowid`` key instead.
|
||||
|
||||
Pass ``"alter: true`` to automatically add any missing columns to the table. This requires the :ref:`actions_alter_table` permission.
|
||||
|
||||
.. _RowUpdateView:
|
||||
|
||||
Updating a row
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
To update a row, make a ``POST`` to ``/<database>/<table>/<row-pks>/-/update``. This requires the :ref:`actions_update_row` permission.
|
||||
|
||||
::
|
||||
|
||||
POST /<database>/<table>/<row-pks>/-/update
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer dstok_<rest-of-token>
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"update": {
|
||||
"text_column": "New text string",
|
||||
"integer_column": 3,
|
||||
"float_column": 3.14
|
||||
}
|
||||
}
|
||||
|
||||
``<row-pks>`` here is the :ref:`tilde-encoded <internals_tilde_encoding>` primary key value of the row to update - or a comma-separated list of primary key values if the table has a composite primary key.
|
||||
|
||||
You only need to pass the columns you want to update. Any other columns will be left unchanged.
|
||||
|
||||
If successful, this will return a ``200`` status code and a ``{"ok": true}`` response body.
|
||||
|
||||
Add ``"return": true`` to the request body to return the updated row:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"update": {
|
||||
"title": "New title"
|
||||
},
|
||||
"return": true
|
||||
}
|
||||
|
||||
The returned JSON will look like this:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"ok": true,
|
||||
"row": {
|
||||
"id": 1,
|
||||
"title": "New title",
|
||||
"other_column": "Will be present here too"
|
||||
}
|
||||
}
|
||||
|
||||
Any errors will return ``{"errors": ["... descriptive message ..."], "ok": false}``, and a ``400`` status code for a bad input or a ``403`` status code for an authentication or permission error.
|
||||
|
||||
Pass ``"alter: true`` to automatically add any missing columns to the table. This requires the :ref:`actions_alter_table` permission.
|
||||
|
||||
.. _RowDeleteView:
|
||||
|
||||
Deleting a row
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
To delete a row, make a ``POST`` to ``/<database>/<table>/<row-pks>/-/delete``. This requires the :ref:`actions_delete_row` permission.
|
||||
|
||||
::
|
||||
|
||||
POST /<database>/<table>/<row-pks>/-/delete
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer dstok_<rest-of-token>
|
||||
|
||||
``<row-pks>`` here is the :ref:`tilde-encoded <internals_tilde_encoding>` primary key value of the row to delete - or a comma-separated list of primary key values if the table has a composite primary key.
|
||||
|
||||
If successful, this will return a ``200`` status code and a ``{"ok": true}`` response body.
|
||||
|
||||
Any errors will return ``{"errors": ["... descriptive message ..."], "ok": false}``, and a ``400`` status code for a bad input or a ``403`` status code for an authentication or permission error.
|
||||
|
||||
.. _TableCreateView:
|
||||
|
||||
Creating a table
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
To create a table, make a ``POST`` to ``/<database>/-/create``. This requires the :ref:`actions_create_table` permission.
|
||||
|
||||
::
|
||||
|
||||
POST /<database>/-/create
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer dstok_<rest-of-token>
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"table": "name_of_new_table",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"name": "title",
|
||||
"type": "text"
|
||||
}
|
||||
],
|
||||
"pk": "id"
|
||||
}
|
||||
|
||||
The JSON here describes the table that will be created:
|
||||
|
||||
* ``table`` is the name of the table to create. This field is required.
|
||||
* ``columns`` is a list of columns to create. Each column is a dictionary with ``name`` and ``type`` keys.
|
||||
|
||||
- ``name`` is the name of the column. This is required.
|
||||
- ``type`` is the type of the column. This is optional - if not provided, ``text`` will be assumed. The valid types are ``text``, ``integer``, ``float`` and ``blob``.
|
||||
|
||||
* ``pk`` is the primary key for the table. This is optional - if not provided, Datasette will create a SQLite table with a hidden ``rowid`` column.
|
||||
|
||||
If the primary key is an integer column, it will be configured to automatically increment for each new record.
|
||||
|
||||
If you set this to ``id`` without including an ``id`` column in the list of ``columns``, Datasette will create an auto-incrementing integer ID column for you.
|
||||
|
||||
* ``pks`` can be used instead of ``pk`` to create a compound primary key. It should be a JSON list of column names to use in that primary key.
|
||||
* ``ignore`` can be set to ``true`` to ignore existing rows by primary key if the table already exists.
|
||||
* ``replace`` can be set to ``true`` to replace existing rows by primary key if the table already exists. This requires the :ref:`actions_update_row` permission.
|
||||
* ``alter`` can be set to ``true`` if you want to automatically add any missing columns to the table. This requires the :ref:`actions_alter_table` permission.
|
||||
|
||||
If the table is successfully created this will return a ``201`` status code and the following response:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"ok": true,
|
||||
"database": "data",
|
||||
"table": "name_of_new_table",
|
||||
"table_url": "http://127.0.0.1:8001/data/name_of_new_table",
|
||||
"table_api_url": "http://127.0.0.1:8001/data/name_of_new_table.json",
|
||||
"schema": "CREATE TABLE [name_of_new_table] (\n [id] INTEGER PRIMARY KEY,\n [title] TEXT\n)"
|
||||
}
|
||||
|
||||
.. _TableCreateView_example:
|
||||
|
||||
Creating a table from example data
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Instead of specifying ``columns`` directly you can instead pass a single example ``row`` or a list of ``rows``.
|
||||
Datasette will create a table with a schema that matches those rows and insert them for you:
|
||||
|
||||
::
|
||||
|
||||
POST /<database>/-/create
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer dstok_<rest-of-token>
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"table": "creatures",
|
||||
"rows": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Tarantula"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Kākāpō"
|
||||
}
|
||||
],
|
||||
"pk": "id"
|
||||
}
|
||||
|
||||
Doing this requires both the :ref:`actions_create_table` and :ref:`actions_insert_row` permissions.
|
||||
|
||||
The ``201`` response here will be similar to the ``columns`` form, but will also include the number of rows that were inserted as ``row_count``:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"ok": true,
|
||||
"database": "data",
|
||||
"table": "creatures",
|
||||
"table_url": "http://127.0.0.1:8001/data/creatures",
|
||||
"table_api_url": "http://127.0.0.1:8001/data/creatures.json",
|
||||
"schema": "CREATE TABLE [creatures] (\n [id] INTEGER PRIMARY KEY,\n [name] TEXT\n)",
|
||||
"row_count": 2
|
||||
}
|
||||
|
||||
You can call the create endpoint multiple times for the same table provided you are specifying the table using the ``rows`` or ``row`` option. New rows will be inserted into the table each time. This means you can use this API if you are unsure if the relevant table has been created yet.
|
||||
|
||||
If you pass a row to the create endpoint with a primary key that already exists you will get an error that looks like this:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"ok": false,
|
||||
"errors": [
|
||||
"UNIQUE constraint failed: creatures.id"
|
||||
]
|
||||
}
|
||||
|
||||
You can avoid this error by passing the same ``"ignore": true`` or ``"replace": true`` options to the create endpoint as you can to the :ref:`insert endpoint <TableInsertView>`.
|
||||
|
||||
To use the ``"replace": true`` option you will also need the :ref:`actions_update_row` permission.
|
||||
|
||||
Pass ``"alter": true`` to automatically add any missing columns to the existing table that are present in the rows you are submitting. This requires the :ref:`actions_alter_table` permission.
|
||||
|
||||
.. _TableDropView:
|
||||
|
||||
Dropping tables
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
To drop a table, make a ``POST`` to ``/<database>/<table>/-/drop``. This requires the :ref:`actions_drop_table` permission.
|
||||
|
||||
::
|
||||
|
||||
POST /<database>/<table>/-/drop
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer dstok_<rest-of-token>
|
||||
|
||||
Without a POST body this will return a status ``200`` with a note about how many rows will be deleted:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"ok": true,
|
||||
"database": "<database>",
|
||||
"table": "<table>",
|
||||
"row_count": 5,
|
||||
"message": "Pass \"confirm\": true to confirm"
|
||||
}
|
||||
|
||||
If you pass the following POST body:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"confirm": true
|
||||
}
|
||||
|
||||
Then the table will be dropped and a status ``200`` response of ``{"ok": true}`` will be returned.
|
||||
|
||||
Any errors will return ``{"errors": ["... descriptive message ..."], "ok": false}``, and a ``400`` status code for a bad input or a ``403`` status code for an authentication or permission error.
|
||||
Link: https://latest.datasette.io/fixtures/sortable.json; rel="alternate"; type="application/json+datasette"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue