mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
render_cell() can now return an awaitable, refs
This commit is contained in:
parent
de5ce2e563
commit
3bb6409a6c
7 changed files with 66 additions and 21 deletions
|
|
@ -361,6 +361,7 @@ class QueryView(DataView):
|
||||||
database=database,
|
database=database,
|
||||||
datasette=self.ds,
|
datasette=self.ds,
|
||||||
)
|
)
|
||||||
|
plugin_value = await await_me_maybe(plugin_value)
|
||||||
if plugin_value is not None:
|
if plugin_value is not None:
|
||||||
display_value = plugin_value
|
display_value = plugin_value
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -198,6 +198,7 @@ class RowTableShared(DataView):
|
||||||
database=database,
|
database=database,
|
||||||
datasette=self.ds,
|
datasette=self.ds,
|
||||||
)
|
)
|
||||||
|
plugin_display_value = await await_me_maybe(plugin_display_value)
|
||||||
if plugin_display_value is not None:
|
if plugin_display_value is not None:
|
||||||
display_value = plugin_display_value
|
display_value = plugin_display_value
|
||||||
elif isinstance(value, bytes):
|
elif isinstance(value, bytes):
|
||||||
|
|
|
||||||
|
|
@ -370,7 +370,7 @@ Lets you customize the display of values within table cells in the HTML table vi
|
||||||
The name of the database
|
The name of the database
|
||||||
|
|
||||||
``datasette`` - :ref:`internals_datasette`
|
``datasette`` - :ref:`internals_datasette`
|
||||||
You can use this to access plugin configuration options via ``datasette.plugin_config(your_plugin_name)``
|
You can use this to access plugin configuration options via ``datasette.plugin_config(your_plugin_name)``, or to execute SQL queries.
|
||||||
|
|
||||||
If your hook returns ``None``, it will be ignored. Use this to indicate that your hook is not able to custom render this particular value.
|
If your hook returns ``None``, it will be ignored. Use this to indicate that your hook is not able to custom render this particular value.
|
||||||
|
|
||||||
|
|
@ -378,6 +378,8 @@ If the hook returns a string, that string will be rendered in the table cell.
|
||||||
|
|
||||||
If you want to return HTML markup you can do so by returning a ``jinja2.Markup`` object.
|
If you want to return HTML markup you can do so by returning a ``jinja2.Markup`` object.
|
||||||
|
|
||||||
|
You can also return an awaitable function which returns a value.
|
||||||
|
|
||||||
Datasette will loop through all available ``render_cell`` hooks and display the value returned by the first one that does not return ``None``.
|
Datasette will loop through all available ``render_cell`` hooks and display the value returned by the first one that does not return ``None``.
|
||||||
|
|
||||||
Here is an example of a custom ``render_cell()`` plugin which looks for values that are a JSON string matching the following format::
|
Here is an example of a custom ``render_cell()`` plugin which looks for values that are a JSON string matching the following format::
|
||||||
|
|
|
||||||
|
|
@ -644,6 +644,7 @@ INSERT INTO simple_primary_key VALUES (1, 'hello');
|
||||||
INSERT INTO simple_primary_key VALUES (2, 'world');
|
INSERT INTO simple_primary_key VALUES (2, 'world');
|
||||||
INSERT INTO simple_primary_key VALUES (3, '');
|
INSERT INTO simple_primary_key VALUES (3, '');
|
||||||
INSERT INTO simple_primary_key VALUES (4, 'RENDER_CELL_DEMO');
|
INSERT INTO simple_primary_key VALUES (4, 'RENDER_CELL_DEMO');
|
||||||
|
INSERT INTO simple_primary_key VALUES (5, 'RENDER_CELL_ASYNC');
|
||||||
|
|
||||||
INSERT INTO primary_key_multiple_columns VALUES (1, 'hey', 'world');
|
INSERT INTO primary_key_multiple_columns VALUES (1, 'hey', 'world');
|
||||||
INSERT INTO primary_key_multiple_columns_explicit_label VALUES (1, 'hey', 'world2');
|
INSERT INTO primary_key_multiple_columns_explicit_label VALUES (1, 'hey', 'world2');
|
||||||
|
|
|
||||||
|
|
@ -97,21 +97,29 @@ def extra_body_script(
|
||||||
|
|
||||||
@hookimpl
|
@hookimpl
|
||||||
def render_cell(value, column, table, database, datasette):
|
def render_cell(value, column, table, database, datasette):
|
||||||
# Render some debug output in cell with value RENDER_CELL_DEMO
|
async def inner():
|
||||||
if value != "RENDER_CELL_DEMO":
|
# Render some debug output in cell with value RENDER_CELL_DEMO
|
||||||
return None
|
if value == "RENDER_CELL_DEMO":
|
||||||
return json.dumps(
|
return json.dumps(
|
||||||
{
|
{
|
||||||
"column": column,
|
"column": column,
|
||||||
"table": table,
|
"table": table,
|
||||||
"database": database,
|
"database": database,
|
||||||
"config": datasette.plugin_config(
|
"config": datasette.plugin_config(
|
||||||
"name-of-plugin",
|
"name-of-plugin",
|
||||||
database=database,
|
database=database,
|
||||||
table=table,
|
table=table,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
elif value == "RENDER_CELL_ASYNC":
|
||||||
|
return (
|
||||||
|
await datasette.get_database(database).execute(
|
||||||
|
"select 'RENDER_CELL_ASYNC_RESULT'"
|
||||||
|
)
|
||||||
|
).single_value()
|
||||||
|
|
||||||
|
return inner
|
||||||
|
|
||||||
|
|
||||||
@hookimpl
|
@hookimpl
|
||||||
|
|
|
||||||
|
|
@ -415,7 +415,7 @@ def test_database_page(app_client):
|
||||||
"name": "simple_primary_key",
|
"name": "simple_primary_key",
|
||||||
"columns": ["id", "content"],
|
"columns": ["id", "content"],
|
||||||
"primary_keys": ["id"],
|
"primary_keys": ["id"],
|
||||||
"count": 4,
|
"count": 5,
|
||||||
"hidden": False,
|
"hidden": False,
|
||||||
"fts_table": None,
|
"fts_table": None,
|
||||||
"foreign_keys": {
|
"foreign_keys": {
|
||||||
|
|
@ -652,6 +652,7 @@ def test_custom_sql(app_client):
|
||||||
{"content": "world"},
|
{"content": "world"},
|
||||||
{"content": ""},
|
{"content": ""},
|
||||||
{"content": "RENDER_CELL_DEMO"},
|
{"content": "RENDER_CELL_DEMO"},
|
||||||
|
{"content": "RENDER_CELL_ASYNC"},
|
||||||
] == data["rows"]
|
] == data["rows"]
|
||||||
assert ["content"] == data["columns"]
|
assert ["content"] == data["columns"]
|
||||||
assert "fixtures" == data["database"]
|
assert "fixtures" == data["database"]
|
||||||
|
|
@ -693,6 +694,7 @@ def test_table_json(app_client):
|
||||||
{"id": "2", "content": "world"},
|
{"id": "2", "content": "world"},
|
||||||
{"id": "3", "content": ""},
|
{"id": "3", "content": ""},
|
||||||
{"id": "4", "content": "RENDER_CELL_DEMO"},
|
{"id": "4", "content": "RENDER_CELL_DEMO"},
|
||||||
|
{"id": "5", "content": "RENDER_CELL_ASYNC"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -723,6 +725,7 @@ def test_table_shape_arrays(app_client):
|
||||||
["2", "world"],
|
["2", "world"],
|
||||||
["3", ""],
|
["3", ""],
|
||||||
["4", "RENDER_CELL_DEMO"],
|
["4", "RENDER_CELL_DEMO"],
|
||||||
|
["5", "RENDER_CELL_ASYNC"],
|
||||||
] == response.json["rows"]
|
] == response.json["rows"]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -736,7 +739,13 @@ def test_table_shape_arrayfirst(app_client):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
assert ["hello", "world", "", "RENDER_CELL_DEMO"] == response.json
|
assert [
|
||||||
|
"hello",
|
||||||
|
"world",
|
||||||
|
"",
|
||||||
|
"RENDER_CELL_DEMO",
|
||||||
|
"RENDER_CELL_ASYNC",
|
||||||
|
] == response.json
|
||||||
|
|
||||||
|
|
||||||
def test_table_shape_objects(app_client):
|
def test_table_shape_objects(app_client):
|
||||||
|
|
@ -746,6 +755,7 @@ def test_table_shape_objects(app_client):
|
||||||
{"id": "2", "content": "world"},
|
{"id": "2", "content": "world"},
|
||||||
{"id": "3", "content": ""},
|
{"id": "3", "content": ""},
|
||||||
{"id": "4", "content": "RENDER_CELL_DEMO"},
|
{"id": "4", "content": "RENDER_CELL_DEMO"},
|
||||||
|
{"id": "5", "content": "RENDER_CELL_ASYNC"},
|
||||||
] == response.json["rows"]
|
] == response.json["rows"]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -756,6 +766,7 @@ def test_table_shape_array(app_client):
|
||||||
{"id": "2", "content": "world"},
|
{"id": "2", "content": "world"},
|
||||||
{"id": "3", "content": ""},
|
{"id": "3", "content": ""},
|
||||||
{"id": "4", "content": "RENDER_CELL_DEMO"},
|
{"id": "4", "content": "RENDER_CELL_DEMO"},
|
||||||
|
{"id": "5", "content": "RENDER_CELL_ASYNC"},
|
||||||
] == response.json
|
] == response.json
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -768,6 +779,7 @@ def test_table_shape_array_nl(app_client):
|
||||||
{"id": "2", "content": "world"},
|
{"id": "2", "content": "world"},
|
||||||
{"id": "3", "content": ""},
|
{"id": "3", "content": ""},
|
||||||
{"id": "4", "content": "RENDER_CELL_DEMO"},
|
{"id": "4", "content": "RENDER_CELL_DEMO"},
|
||||||
|
{"id": "5", "content": "RENDER_CELL_ASYNC"},
|
||||||
] == results
|
] == results
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -788,6 +800,7 @@ def test_table_shape_object(app_client):
|
||||||
"2": {"id": "2", "content": "world"},
|
"2": {"id": "2", "content": "world"},
|
||||||
"3": {"id": "3", "content": ""},
|
"3": {"id": "3", "content": ""},
|
||||||
"4": {"id": "4", "content": "RENDER_CELL_DEMO"},
|
"4": {"id": "4", "content": "RENDER_CELL_DEMO"},
|
||||||
|
"5": {"id": "5", "content": "RENDER_CELL_ASYNC"},
|
||||||
} == response.json
|
} == response.json
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1145,12 +1158,21 @@ def test_searchable_invalid_column(app_client):
|
||||||
("/fixtures/simple_primary_key.json?content=hello", [["1", "hello"]]),
|
("/fixtures/simple_primary_key.json?content=hello", [["1", "hello"]]),
|
||||||
(
|
(
|
||||||
"/fixtures/simple_primary_key.json?content__contains=o",
|
"/fixtures/simple_primary_key.json?content__contains=o",
|
||||||
[["1", "hello"], ["2", "world"], ["4", "RENDER_CELL_DEMO"]],
|
[
|
||||||
|
["1", "hello"],
|
||||||
|
["2", "world"],
|
||||||
|
["4", "RENDER_CELL_DEMO"],
|
||||||
|
],
|
||||||
),
|
),
|
||||||
("/fixtures/simple_primary_key.json?content__exact=", [["3", ""]]),
|
("/fixtures/simple_primary_key.json?content__exact=", [["3", ""]]),
|
||||||
(
|
(
|
||||||
"/fixtures/simple_primary_key.json?content__not=world",
|
"/fixtures/simple_primary_key.json?content__not=world",
|
||||||
[["1", "hello"], ["3", ""], ["4", "RENDER_CELL_DEMO"]],
|
[
|
||||||
|
["1", "hello"],
|
||||||
|
["3", ""],
|
||||||
|
["4", "RENDER_CELL_DEMO"],
|
||||||
|
["5", "RENDER_CELL_ASYNC"],
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
@ -1163,7 +1185,11 @@ def test_table_filter_queries_multiple_of_same_type(app_client):
|
||||||
response = app_client.get(
|
response = app_client.get(
|
||||||
"/fixtures/simple_primary_key.json?content__not=world&content__not=hello"
|
"/fixtures/simple_primary_key.json?content__not=world&content__not=hello"
|
||||||
)
|
)
|
||||||
assert [["3", ""], ["4", "RENDER_CELL_DEMO"]] == response.json["rows"]
|
assert [
|
||||||
|
["3", ""],
|
||||||
|
["4", "RENDER_CELL_DEMO"],
|
||||||
|
["5", "RENDER_CELL_ASYNC"],
|
||||||
|
] == response.json["rows"]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif(not detect_json1(), reason="Requires the SQLite json1 module")
|
@pytest.mark.skipif(not detect_json1(), reason="Requires the SQLite json1 module")
|
||||||
|
|
@ -1293,6 +1319,7 @@ def test_view(app_client):
|
||||||
{"upper_content": "WORLD", "content": "world"},
|
{"upper_content": "WORLD", "content": "world"},
|
||||||
{"upper_content": "", "content": ""},
|
{"upper_content": "", "content": ""},
|
||||||
{"upper_content": "RENDER_CELL_DEMO", "content": "RENDER_CELL_DEMO"},
|
{"upper_content": "RENDER_CELL_DEMO", "content": "RENDER_CELL_DEMO"},
|
||||||
|
{"upper_content": "RENDER_CELL_ASYNC", "content": "RENDER_CELL_ASYNC"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -185,6 +185,11 @@ def test_hook_render_cell_demo(app_client):
|
||||||
} == json.loads(td.string)
|
} == json.loads(td.string)
|
||||||
|
|
||||||
|
|
||||||
|
def test_hook_render_cell_async(app_client):
|
||||||
|
response = app_client.get("/fixtures?sql=select+'RENDER_CELL_ASYNC'")
|
||||||
|
assert b"RENDER_CELL_ASYNC_RESULT" in response.body
|
||||||
|
|
||||||
|
|
||||||
def test_plugin_config(app_client):
|
def test_plugin_config(app_client):
|
||||||
assert {"depth": "table"} == app_client.ds.plugin_config(
|
assert {"depth": "table"} == app_client.ds.plugin_config(
|
||||||
"name-of-plugin", database="fixtures", table="sortable"
|
"name-of-plugin", database="fixtures", table="sortable"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue