diff --git a/datasette/app.py b/datasette/app.py index 5c1c3e83..75c96db4 100644 --- a/datasette/app.py +++ b/datasette/app.py @@ -13,6 +13,7 @@ from pathlib import Path import click from markupsafe import Markup from jinja2 import ChoiceLoader, Environment, FileSystemLoader, PrefixLoader +from jinja2.exceptions import TemplateNotFound import uvicorn from .views.base import DatasetteError, ureg, AsgiRouter @@ -488,7 +489,10 @@ class Datasette: if hasattr(asyncio, "all_tasks"): tasks = asyncio.all_tasks() d.update( - {"num_tasks": len(tasks), "tasks": [_cleaner_task_str(t) for t in tasks]} + { + "num_tasks": len(tasks), + "tasks": [_cleaner_task_str(t) for t in tasks], + } ) return d @@ -658,7 +662,16 @@ class DatasetteRouter(AsgiRouter): path += b"?" + scope["query_string"] await asgi_send_redirect(send, path.decode("latin1")) else: - await super().handle_404(scope, receive, send) + # Is there a pages/* template matching this path? + template_path = os.path.join("pages", *scope["path"].split("/")) + ".html" + try: + template = self.ds.jinja_env.select_template([template_path]) + except TemplateNotFound: + template = None + if template: + await asgi_send_html(send, await template.render_async(), status=200) + else: + await super().handle_404(scope, receive, send) async def handle_500(self, scope, receive, send, exception): title = None diff --git a/datasette/utils/asgi.py b/datasette/utils/asgi.py index bafcfb4a..634a596f 100644 --- a/datasette/utils/asgi.py +++ b/datasette/utils/asgi.py @@ -99,6 +99,8 @@ class AsgiRouter: new_scope = dict(scope, url_route={"kwargs": match.groupdict()}) try: return await view(new_scope, receive, send) + except NotFound: + return await self.handle_404(scope, receive, send) except Exception as exception: return await self.handle_500(scope, receive, send, exception) return await self.handle_404(scope, receive, send)