mirror of
https://github.com/simonw/datasette.git
synced 2026-07-08 08:34:42 +02:00
Row update return:true responds with rows list, matching insert/upsert
Row update previously returned a singular "row" object where insert and upsert return a "rows" list. All write endpoints now use "rows". Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GrHZSypDfMnym1tM5XJAFZ
This commit is contained in:
parent
6488b7a30e
commit
b09dceea88
7 changed files with 40 additions and 13 deletions
|
|
@ -828,7 +828,7 @@ class RowUpdateView(BaseView):
|
|||
resolved.sql, resolved.params, truncate=True
|
||||
)
|
||||
returned_row = results.dicts()[0]
|
||||
result["row"] = returned_row
|
||||
result["rows"] = [returned_row]
|
||||
|
||||
await self.ds.track_event(
|
||||
UpdateRowEvent(
|
||||
|
|
|
|||
|
|
@ -1955,11 +1955,13 @@ The returned JSON will look like this:
|
|||
|
||||
{
|
||||
"ok": true,
|
||||
"row": {
|
||||
"id": 1,
|
||||
"title": "New title",
|
||||
"other_column": "Will be present here too"
|
||||
}
|
||||
"rows": [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "New title",
|
||||
"other_column": "Will be present here too"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Any errors will use the :ref:`standard error format <json_api_errors>`, with a ``400`` status code for a bad input or a ``403`` status code for an authentication or permission error.
|
||||
|
|
|
|||
|
|
@ -958,8 +958,8 @@ does not change the SQLite schema.
|
|||
`"Invalid keys: ..."`; write failures (bad column, constraint violation) →
|
||||
400 with the message.
|
||||
- **Response** — 200 `{"ok": true}`; with `return: true`,
|
||||
`{"ok": true, "row": {...}}` (singular `row`, unlike insert/upsert's
|
||||
`rows`). Emits `update-row`.
|
||||
`{"ok": true, "rows": [{...}]}` — a single-item list, matching
|
||||
insert/upsert. Emits `update-row`.
|
||||
|
||||
### POST /\<database\>/\<table\>/\<pks\>/-/delete
|
||||
|
||||
|
|
|
|||
|
|
@ -160,10 +160,11 @@ Endpoints disagree about the success envelope:
|
|||
(index.py:147-161); `/-/databases.json` returns an **array**; the database
|
||||
page returns `tables` as an array. Choose arrays-of-objects everywhere
|
||||
(objects-keyed-by-name break when names need ordering or pagination).
|
||||
- Insert/upsert with `return: true` respond with `rows` (plural, list); row
|
||||
- ~~Insert/upsert with `return: true` respond with `rows` (plural, list); row
|
||||
update with `return: true` responds with `row` (singular, object)
|
||||
(views/row.py:837-844). Pick one (`rows` everywhere, even for one row,
|
||||
matches the read API).
|
||||
matches the read API).~~ ✅ **Done** — row update now returns
|
||||
`rows: [{...}]`.
|
||||
|
||||
### 2b. `_extra`/`_shape` support is uneven (P2)
|
||||
|
||||
|
|
|
|||
|
|
@ -1481,9 +1481,9 @@ async def test_update_row(ds_write, input, expected_errors, use_return):
|
|||
|
||||
assert response.json()["ok"] is True
|
||||
if not use_return:
|
||||
assert "row" not in response.json()
|
||||
assert "rows" not in response.json()
|
||||
else:
|
||||
returned_row = response.json()["row"]
|
||||
returned_row = response.json()["rows"][0]
|
||||
assert returned_row["id"] == pk
|
||||
for k, v in input.items():
|
||||
assert returned_row[k] == v
|
||||
|
|
|
|||
|
|
@ -507,3 +507,27 @@ async def test_query_html_without_sql_is_still_the_editor(ds_client):
|
|||
response = await ds_client.get("/fixtures/-/query")
|
||||
assert response.status_code == 200
|
||||
assert response.headers["content-type"].startswith("text/html")
|
||||
|
||||
|
||||
# Write API return:true responses use "rows" consistently
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_row_update_return_uses_rows_list(ds_error_shape):
|
||||
await ds_error_shape.client.post(
|
||||
"/data/docs/-/insert",
|
||||
json={"row": {"id": 1, "title": "One"}},
|
||||
headers={"Content-Type": "application/json"},
|
||||
actor={"id": "root"},
|
||||
)
|
||||
response = await ds_error_shape.client.post(
|
||||
"/data/docs/1/-/update",
|
||||
json={"update": {"title": "Updated"}, "return": True},
|
||||
headers={"Content-Type": "application/json"},
|
||||
actor={"id": "root"},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["ok"] is True
|
||||
assert "row" not in data
|
||||
assert data["rows"] == [{"id": 1, "title": "Updated"}]
|
||||
|
|
|
|||
|
|
@ -1629,7 +1629,7 @@ async def test_row_update_sets_message():
|
|||
json={"update": {"name": long_name}, "return": True},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json()["row"]["name"] == long_name
|
||||
assert response.json()["rows"][0]["name"] == long_name
|
||||
assert ds.unsign(response.cookies["ds_messages"], "messages") == [
|
||||
["Updated row 1 ({})".format(truncated_name), ds.INFO]
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue