mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
render_template refactor, refs #577
This commit is contained in:
parent
286ed286b6
commit
3425d4924e
2 changed files with 100 additions and 85 deletions
|
|
@ -27,6 +27,7 @@ from .utils import (
|
|||
QueryInterrupted,
|
||||
escape_css_string,
|
||||
escape_sqlite,
|
||||
format_bytes,
|
||||
get_plugins,
|
||||
module_from_path,
|
||||
sqlite3,
|
||||
|
|
@ -526,6 +527,95 @@ class Datasette:
|
|||
for renderer in hook_renderers:
|
||||
self.renderers[renderer["extension"]] = renderer["callback"]
|
||||
|
||||
def _asset_urls(self, key, template, context):
|
||||
# Flatten list-of-lists from plugins:
|
||||
seen_urls = set()
|
||||
for url_or_dict in itertools.chain(
|
||||
itertools.chain.from_iterable(
|
||||
getattr(pm.hook, key)(
|
||||
template=template.name,
|
||||
database=context.get("database"),
|
||||
table=context.get("table"),
|
||||
datasette=self.ds,
|
||||
)
|
||||
),
|
||||
(self.ds.metadata(key) or []),
|
||||
):
|
||||
if isinstance(url_or_dict, dict):
|
||||
url = url_or_dict["url"]
|
||||
sri = url_or_dict.get("sri")
|
||||
else:
|
||||
url = url_or_dict
|
||||
sri = None
|
||||
if url in seen_urls:
|
||||
continue
|
||||
seen_urls.add(url)
|
||||
if sri:
|
||||
yield {"url": url, "sri": sri}
|
||||
else:
|
||||
yield {"url": url}
|
||||
|
||||
async def render_template(
|
||||
self, templates, context=None, request=None, view_name=None
|
||||
):
|
||||
if isinstance(templates, str):
|
||||
templates = [templates]
|
||||
template = self.jinja_env.select_template(templates)
|
||||
select_templates = [
|
||||
"{}{}".format("*" if template_name == template.name else "", template_name)
|
||||
for template_name in templates
|
||||
]
|
||||
body_scripts = []
|
||||
# pylint: disable=no-member
|
||||
for script in pm.hook.extra_body_script(
|
||||
template=template.name,
|
||||
database=context.get("database"),
|
||||
table=context.get("table"),
|
||||
view_name=view_name,
|
||||
datasette=self,
|
||||
):
|
||||
body_scripts.append(Markup(script))
|
||||
|
||||
extra_template_vars = {}
|
||||
# pylint: disable=no-member
|
||||
for extra_vars in pm.hook.extra_template_vars(
|
||||
template=template.name,
|
||||
database=context.get("database"),
|
||||
table=context.get("table"),
|
||||
view_name=view_name,
|
||||
request=request,
|
||||
datasette=self,
|
||||
):
|
||||
if callable(extra_vars):
|
||||
extra_vars = extra_vars()
|
||||
if asyncio.iscoroutine(extra_vars):
|
||||
extra_vars = await extra_vars
|
||||
assert isinstance(extra_vars, dict), "extra_vars is of type {}".format(
|
||||
type(extra_vars)
|
||||
)
|
||||
extra_template_vars.update(extra_vars)
|
||||
|
||||
template_context = {
|
||||
**context,
|
||||
**{
|
||||
"app_css_hash": self.app_css_hash(),
|
||||
"select_templates": select_templates,
|
||||
"zip": zip,
|
||||
"body_scripts": body_scripts,
|
||||
"extra_css_urls": self._asset_urls("extra_css_urls", template, context),
|
||||
"extra_js_urls": self._asset_urls("extra_js_urls", template, context),
|
||||
"format_bytes": format_bytes,
|
||||
},
|
||||
**extra_template_vars,
|
||||
}
|
||||
if request.args.get("_context") and self.config("template_debug"):
|
||||
return Response.html(
|
||||
"<pre>{}</pre>".format(
|
||||
escape(json.dumps(template_context, default=repr, indent=4))
|
||||
)
|
||||
)
|
||||
return Response.html(await template.render_async(template_context))
|
||||
|
||||
def app(self):
|
||||
"Returns an ASGI app function that serves the whole of Datasette"
|
||||
default_templates = str(app_root / "datasette" / "templates")
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ from datasette.utils import (
|
|||
QueryInterrupted,
|
||||
InvalidSql,
|
||||
LimitedWriter,
|
||||
format_bytes,
|
||||
is_url,
|
||||
path_with_added_args,
|
||||
path_with_removed_args,
|
||||
|
|
@ -65,34 +64,6 @@ class BaseView(AsgiView):
|
|||
response.body = b""
|
||||
return response
|
||||
|
||||
def _asset_urls(self, key, template, context):
|
||||
# Flatten list-of-lists from plugins:
|
||||
seen_urls = set()
|
||||
for url_or_dict in itertools.chain(
|
||||
itertools.chain.from_iterable(
|
||||
getattr(pm.hook, key)(
|
||||
template=template.name,
|
||||
database=context.get("database"),
|
||||
table=context.get("table"),
|
||||
datasette=self.ds,
|
||||
)
|
||||
),
|
||||
(self.ds.metadata(key) or []),
|
||||
):
|
||||
if isinstance(url_or_dict, dict):
|
||||
url = url_or_dict["url"]
|
||||
sri = url_or_dict.get("sri")
|
||||
else:
|
||||
url = url_or_dict
|
||||
sri = None
|
||||
if url in seen_urls:
|
||||
continue
|
||||
seen_urls.add(url)
|
||||
if sri:
|
||||
yield {"url": url, "sri": sri}
|
||||
else:
|
||||
yield {"url": url}
|
||||
|
||||
def database_url(self, database):
|
||||
db = self.ds.databases[database]
|
||||
if self.ds.config("hash_urls") and db.hash:
|
||||
|
|
@ -104,63 +75,17 @@ class BaseView(AsgiView):
|
|||
return "ff0000"
|
||||
|
||||
async def render(self, templates, request, context):
|
||||
template = self.ds.jinja_env.select_template(templates)
|
||||
select_templates = [
|
||||
"{}{}".format("*" if template_name == template.name else "", template_name)
|
||||
for template_name in templates
|
||||
]
|
||||
body_scripts = []
|
||||
# pylint: disable=no-member
|
||||
for script in pm.hook.extra_body_script(
|
||||
template=template.name,
|
||||
database=context.get("database"),
|
||||
table=context.get("table"),
|
||||
view_name=self.name,
|
||||
datasette=self.ds,
|
||||
):
|
||||
body_scripts.append(jinja2.Markup(script))
|
||||
|
||||
extra_template_vars = {}
|
||||
# pylint: disable=no-member
|
||||
for extra_vars in pm.hook.extra_template_vars(
|
||||
template=template.name,
|
||||
database=context.get("database"),
|
||||
table=context.get("table"),
|
||||
view_name=self.name,
|
||||
request=request,
|
||||
datasette=self.ds,
|
||||
):
|
||||
if callable(extra_vars):
|
||||
extra_vars = extra_vars()
|
||||
if asyncio.iscoroutine(extra_vars):
|
||||
extra_vars = await extra_vars
|
||||
assert isinstance(extra_vars, dict), "extra_vars is of type {}".format(
|
||||
type(extra_vars)
|
||||
)
|
||||
extra_template_vars.update(extra_vars)
|
||||
|
||||
template_context = {
|
||||
**context,
|
||||
**{
|
||||
"app_css_hash": self.ds.app_css_hash(),
|
||||
"select_templates": select_templates,
|
||||
"zip": zip,
|
||||
"body_scripts": body_scripts,
|
||||
"extra_css_urls": self._asset_urls("extra_css_urls", template, context),
|
||||
"extra_js_urls": self._asset_urls("extra_js_urls", template, context),
|
||||
"format_bytes": format_bytes,
|
||||
"database_url": self.database_url,
|
||||
"database_color": self.database_color,
|
||||
return await self.ds.render_template(
|
||||
templates,
|
||||
{
|
||||
**context,
|
||||
**{
|
||||
"database_url": self.database_url,
|
||||
"database_color": self.database_color,
|
||||
},
|
||||
},
|
||||
**extra_template_vars,
|
||||
}
|
||||
if request.args.get("_context") and self.ds.config("template_debug"):
|
||||
return Response.html(
|
||||
"<pre>{}</pre>".format(
|
||||
escape(json.dumps(template_context, default=repr, indent=4))
|
||||
)
|
||||
)
|
||||
return Response.html(await template.render_async(template_context))
|
||||
request=request,
|
||||
)
|
||||
|
||||
|
||||
class DataView(BaseView):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue