html_url,issue_url,id,node_id,user,created_at,updated_at,author_association,body,reactions,issue,performed_via_github_app
https://github.com/simonw/datasette/issues/1072#issuecomment-719986698,https://api.github.com/repos/simonw/datasette/issues/1072,719986698,MDEyOklzc3VlQ29tbWVudDcxOTk4NjY5OA==,9599,2020-10-31T20:48:17Z,2020-10-31T20:48:17Z,OWNER,Here's the `datasette-edit-templates` plugin WIP I had before removing the hook: https://github.com/simonw/datasette-edit-templates/tree/82855c2612b84bc09c48fca885f831633a0d1552,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",733499930,
https://github.com/simonw/datasette/issues/1072#issuecomment-719955491,https://api.github.com/repos/simonw/datasette/issues/1072,719955491,MDEyOklzc3VlQ29tbWVudDcxOTk1NTQ5MQ==,9599,2020-10-31T16:20:58Z,2020-10-31T16:20:58Z,OWNER,"Here's the proof of concept `FunctionLoader` that showed me that this wasn't going to work:
```diff
diff --git a/datasette/app.py b/datasette/app.py
index 4b28e71..b076be7 100644
--- a/datasette/app.py
+++ b/datasette/app.py
@@ -21,7 +21,7 @@ from pathlib import Path
from markupsafe import Markup
from itsdangerous import URLSafeSerializer
import jinja2
-from jinja2 import ChoiceLoader, Environment, FileSystemLoader, PrefixLoader
+from jinja2 import ChoiceLoader, Environment, FileSystemLoader, FunctionLoader, PrefixLoader
from jinja2.environment import Template
from jinja2.exceptions import TemplateNotFound
import uvicorn
@@ -300,6 +300,7 @@ class Datasette:
template_paths.append(default_templates)
template_loader = ChoiceLoader(
[
+ FunctionLoader(self._load_template_from_plugins),
FileSystemLoader(template_paths),
# Support {% extends ""default:table.html"" %}:
PrefixLoader(
@@ -322,6 +323,17 @@ class Datasette:
self._root_token = secrets.token_hex(32)
self.client = DatasetteClient(self)
+ def _load_template_from_plugins(self, template):
+ # ""If auto reloading is enabled it’s called to check if the template changed""
+ uptodatefunc = lambda: True
+ source = pm.hook.load_template(
+ template=template,
+ datasette=self,
+ )
+ if source is None:
+ return None
+ return source, template, uptodatefunc
+
@property
def urls(self):
return Urls(self)
@@ -719,35 +731,7 @@ class Datasette:
else:
if isinstance(templates, str):
templates = [templates]
-
- # Give plugins first chance at loading the template
- break_outer = False
- plugin_template_source = None
- plugin_template_name = None
- template_name = None
- for template_name in templates:
- if break_outer:
- break
- plugin_template_source = pm.hook.load_template(
- template=template_name,
- request=request,
- datasette=self,
- )
- plugin_template_source = await await_me_maybe(plugin_template_source)
- if plugin_template_source:
- break_outer = True
- plugin_template_name = template_name
- break
- if plugin_template_source is not None:
- template = self.jinja_env.from_string(plugin_template_source)
- else:
- template = self.jinja_env.select_template(templates)
- for template_name in templates:
- from_plugin = template_name == plugin_template_name
- used = from_plugin or template_name == template.name
- templates_considered.append(
- {""name"": template_name, ""used"": used, ""from_plugin"": from_plugin}
- )
+ template = self.jinja_env.select_template(templates)
body_scripts = []
# pylint: disable=no-member
for extra_script in pm.hook.extra_body_script(
diff --git a/datasette/hookspecs.py b/datasette/hookspecs.py
index ca84b35..7804def 100644
--- a/datasette/hookspecs.py
+++ b/datasette/hookspecs.py
@@ -50,7 +50,7 @@ def extra_template_vars(
@hookspec(firstresult=True)
-def load_template(template, request, datasette):
+def load_template(template, datasette):
""Load the specified template, returning the template code as a string""
diff --git a/docs/plugin_hooks.rst b/docs/plugin_hooks.rst
index 3c57b6a..8f2704e 100644
--- a/docs/plugin_hooks.rst
+++ b/docs/plugin_hooks.rst
@@ -273,15 +273,12 @@ Example: `datasette-cluster-map >> def load_template(name):
... if name == 'index.html':
... return '...'
...
>>> loader = FunctionLoader(load_template)
```
Just one catch: I need to be able to load templates asynchronously, because they live in the database. Let's hope Jinja has a mechanism for that!","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",733499930,
https://github.com/simonw/datasette/issues/1072#issuecomment-719785005,https://api.github.com/repos/simonw/datasette/issues/1072,719785005,MDEyOklzc3VlQ29tbWVudDcxOTc4NTAwNQ==,9599,2020-10-30T20:36:22Z,2020-10-30T20:36:22Z,OWNER,"It should be easy enough to show a comment that says which original template names were considered, but I may not be able to show which one was actually used (or which ones came from plugins).","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",733499930,
https://github.com/simonw/datasette/issues/1072#issuecomment-719784606,https://api.github.com/repos/simonw/datasette/issues/1072,719784606,MDEyOklzc3VlQ29tbWVudDcxOTc4NDYwNg==,9599,2020-10-30T20:35:33Z,2020-10-30T20:35:33Z,OWNER,"To fix this I think I need to move the `load_template` implementation into a Jinja template loader.
I'm not sure I'll be able to keep the `Templates considered` comment working though:
https://github.com/simonw/datasette/blob/a2a709072059c6b3da365df9a332ca744c2079e9/datasette/app.py#L745-L750","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",733499930,