Template slot family of plugin hooks - top_homepage() and others

New plugin hooks:

top_homepage
top_database
top_table
top_row
top_query
top_canned_query

New datasette.utils.make_slot_function()

Closes #1191
This commit is contained in:
Simon Willison 2024-01-30 19:54:03 -08:00 committed by GitHub
commit c3caf36af7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 324 additions and 7 deletions

View file

@ -1,5 +1,4 @@
from dataclasses import dataclass, field
from typing import Callable
from urllib.parse import parse_qsl, urlencode
import asyncio
import hashlib
@ -18,6 +17,7 @@ from datasette.utils import (
call_with_supported_arguments,
derive_named_parameters,
format_bytes,
make_slot_function,
tilde_decode,
to_css_class,
validate_sql_select,
@ -161,6 +161,9 @@ class DatabaseView(View):
f"{'*' if template_name == template.name else ''}{template_name}"
for template_name in templates
],
"top_database": make_slot_function(
"top_database", datasette, request, database=database
),
}
return Response.html(
await datasette.render_template(
@ -246,6 +249,12 @@ class QueryContext:
"help": "List of templates that were considered for rendering this page"
}
)
top_query: callable = field(
metadata={"help": "Callable to render the top_query slot"}
)
top_canned_query: callable = field(
metadata={"help": "Callable to render the top_canned_query slot"}
)
async def get_tables(datasette, request, db):
@ -727,6 +736,16 @@ class QueryView(View):
f"{'*' if template_name == template.name else ''}{template_name}"
for template_name in templates
],
top_query=make_slot_function(
"top_query", datasette, request, database=database, sql=sql
),
top_canned_query=make_slot_function(
"top_canned_query",
datasette,
request,
database=database,
query_name=canned_query["name"] if canned_query else None,
),
),
request=request,
view_name="database",

View file

@ -1,10 +1,12 @@
import hashlib
import json
from datasette.utils import add_cors_headers, CustomJSONEncoder
from datasette.plugins import pm
from datasette.utils import add_cors_headers, make_slot_function, CustomJSONEncoder
from datasette.utils.asgi import Response
from datasette.version import __version__
from markupsafe import Markup
from .base import BaseView
@ -142,5 +144,8 @@ class IndexView(BaseView):
"private": not await self.ds.permission_allowed(
None, "view-instance"
),
"top_homepage": make_slot_function(
"top_homepage", self.ds, request
),
},
)

View file

@ -2,11 +2,9 @@ from datasette.utils.asgi import NotFound, Forbidden, Response
from datasette.database import QueryInterrupted
from .base import DataView, BaseView, _error
from datasette.utils import (
tilde_decode,
urlsafe_components,
make_slot_function,
to_css_class,
escape_sqlite,
row_sql_params_pks,
)
import json
import sqlite_utils
@ -73,6 +71,14 @@ class RowView(DataView):
.get(database, {})
.get("tables", {})
.get(table, {}),
"top_row": make_slot_function(
"top_row",
self.ds,
request,
database=resolved.db.name,
table=resolved.table,
row=rows[0],
),
}
data = {

View file

@ -17,6 +17,7 @@ from datasette.utils import (
append_querystring,
compound_keys_after_sql,
format_bytes,
make_slot_function,
tilde_encode,
escape_sqlite,
filters_should_redirect,
@ -842,6 +843,13 @@ async def table_view_traced(datasette, request):
f"{'*' if template_name == template.name else ''}{template_name}"
for template_name in templates
],
top_table=make_slot_function(
"top_table",
datasette,
request,
database=resolved.db.name,
table=resolved.table,
),
),
request=request,
view_name="table",