mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
register_output_renderer can now return Response, closes #953
This commit is contained in:
parent
86aefc39c5
commit
799ecae948
5 changed files with 42 additions and 16 deletions
|
|
@ -455,13 +455,17 @@ class DataView(BaseView):
|
||||||
result = await result
|
result = await result
|
||||||
if result is None:
|
if result is None:
|
||||||
raise NotFound("No data")
|
raise NotFound("No data")
|
||||||
|
if isinstance(result, dict):
|
||||||
r = Response(
|
r = Response(
|
||||||
body=result.get("body"),
|
body=result.get("body"),
|
||||||
status=result.get("status_code", 200),
|
status=result.get("status_code", 200),
|
||||||
content_type=result.get("content_type", "text/plain"),
|
content_type=result.get("content_type", "text/plain"),
|
||||||
headers=result.get("headers"),
|
headers=result.get("headers"),
|
||||||
)
|
)
|
||||||
|
elif isinstance(result, Response):
|
||||||
|
r = result
|
||||||
|
else:
|
||||||
|
assert False, "{} should be dict or Response".format(result)
|
||||||
else:
|
else:
|
||||||
extras = {}
|
extras = {}
|
||||||
if callable(extra_template_data):
|
if callable(extra_template_data):
|
||||||
|
|
|
||||||
|
|
@ -455,7 +455,9 @@ When a request is received, the ``"render"`` callback function is called with ze
|
||||||
``view_name`` - string
|
``view_name`` - string
|
||||||
The name of the current view being called. ``index``, ``database``, ``table``, and ``row`` are the most important ones.
|
The name of the current view being called. ``index``, ``database``, ``table``, and ``row`` are the most important ones.
|
||||||
|
|
||||||
The callback function can return ``None``, if it is unable to render the data, or a dictionary with the following keys:
|
The callback function can return ``None``, if it is unable to render the data, or a :ref:`internals_response` that will be returned to the caller.
|
||||||
|
|
||||||
|
It can also return a dictionary with the following keys. This format is **deprecated** as-of Datasette 0.49 and will be removed by Datasette 1.0.
|
||||||
|
|
||||||
``body`` - string or bytes, optional
|
``body`` - string or bytes, optional
|
||||||
The response body, default empty
|
The response body, default empty
|
||||||
|
|
@ -474,9 +476,7 @@ A simple example of an output renderer callback function:
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
def render_demo():
|
def render_demo():
|
||||||
return {
|
return Response.text("Hello World")
|
||||||
"body": "Hello World"
|
|
||||||
}
|
|
||||||
|
|
||||||
Here is a more complex example:
|
Here is a more complex example:
|
||||||
|
|
||||||
|
|
@ -490,11 +490,11 @@ Here is a more complex example:
|
||||||
lines.append("=" * len(first_row))
|
lines.append("=" * len(first_row))
|
||||||
for row in rows:
|
for row in rows:
|
||||||
lines.append(" | ".join(row))
|
lines.append(" | ".join(row))
|
||||||
return {
|
return Response(
|
||||||
"body": "\n".join(lines),
|
"\n".join(lines),
|
||||||
"content_type": "text/plain; charset=utf-8",
|
content_type="text/plain; charset=utf-8",
|
||||||
"headers": {"x-sqlite-version": result.first()[0]},
|
headers={"x-sqlite-version": result.first()[0]}
|
||||||
}
|
)
|
||||||
|
|
||||||
And here is an example ``can_render`` function which returns ``True`` only if the query results contain the columns ``atom_id``, ``atom_title`` and ``atom_updated``:
|
And here is an example ``can_render`` function which returns ``True`` only if the query results contain the columns ``atom_id``, ``atom_title`` and ``atom_updated``:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
from datasette import hookimpl
|
from datasette import hookimpl
|
||||||
|
from datasette.utils.asgi import Response
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -56,6 +57,12 @@ def render_test_no_parameters():
|
||||||
return {"body": "Hello"}
|
return {"body": "Hello"}
|
||||||
|
|
||||||
|
|
||||||
|
async def render_response(request):
|
||||||
|
if request.args.get("_broken"):
|
||||||
|
return "this should break"
|
||||||
|
return Response.json({"this_is": "json"})
|
||||||
|
|
||||||
|
|
||||||
@hookimpl
|
@hookimpl
|
||||||
def register_output_renderer(datasette):
|
def register_output_renderer(datasette):
|
||||||
return [
|
return [
|
||||||
|
|
@ -65,4 +72,5 @@ def register_output_renderer(datasette):
|
||||||
"can_render": can_render,
|
"can_render": can_render,
|
||||||
},
|
},
|
||||||
{"extension": "testnone", "callback": render_test_no_parameters},
|
{"extension": "testnone", "callback": render_test_no_parameters},
|
||||||
|
{"extension": "testresponse", "render": render_response},
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -559,6 +559,7 @@ def test_table_csv_json_export_interface(app_client):
|
||||||
"simple_primary_key.json?id__gt=2",
|
"simple_primary_key.json?id__gt=2",
|
||||||
"simple_primary_key.testall?id__gt=2",
|
"simple_primary_key.testall?id__gt=2",
|
||||||
"simple_primary_key.testnone?id__gt=2",
|
"simple_primary_key.testnone?id__gt=2",
|
||||||
|
"simple_primary_key.testresponse?id__gt=2",
|
||||||
"simple_primary_key.csv?id__gt=2&_size=max",
|
"simple_primary_key.csv?id__gt=2&_size=max",
|
||||||
"#export",
|
"#export",
|
||||||
]
|
]
|
||||||
|
|
@ -597,6 +598,7 @@ def test_csv_json_export_links_include_labels_if_foreign_keys(app_client):
|
||||||
"facetable.json?_labels=on",
|
"facetable.json?_labels=on",
|
||||||
"facetable.testall?_labels=on",
|
"facetable.testall?_labels=on",
|
||||||
"facetable.testnone?_labels=on",
|
"facetable.testnone?_labels=on",
|
||||||
|
"facetable.testresponse?_labels=on",
|
||||||
"facetable.csv?_labels=on&_size=max",
|
"facetable.csv?_labels=on&_size=max",
|
||||||
"#export",
|
"#export",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -479,6 +479,18 @@ def test_hook_register_output_renderer_custom_headers(app_client):
|
||||||
assert "2" == response.headers["x-gosh"]
|
assert "2" == response.headers["x-gosh"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_hook_register_output_renderer_returning_response(app_client):
|
||||||
|
response = app_client.get("/fixtures/facetable.testresponse")
|
||||||
|
assert 200 == response.status
|
||||||
|
assert response.json == {"this_is": "json"}
|
||||||
|
|
||||||
|
|
||||||
|
def test_hook_register_output_renderer_returning_broken_value(app_client):
|
||||||
|
response = app_client.get("/fixtures/facetable.testresponse?_broken=1")
|
||||||
|
assert 500 == response.status
|
||||||
|
assert "this should break should be dict or Response" in response.text
|
||||||
|
|
||||||
|
|
||||||
def test_hook_register_output_renderer_can_render(app_client):
|
def test_hook_register_output_renderer_can_render(app_client):
|
||||||
response = app_client.get("/fixtures/facetable?_no_can_render=1")
|
response = app_client.get("/fixtures/facetable?_no_can_render=1")
|
||||||
assert response.status == 200
|
assert response.status == 200
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue