Skip to content

Commit 13267d3

Browse files
committed
Refactor bolt.jinja to bolt.templates, render templates immediately
1 parent f402c7b commit 13267d3

File tree

27 files changed

+83
-243
lines changed

27 files changed

+83
-243
lines changed

bolt-auth/bolt/auth/forms.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import unicodedata
22

3-
from bolt import forms, jinja
3+
from bolt import forms
44
from bolt.auth import authenticate, get_user_model, password_validation
55
from bolt.auth.models import User
66
from bolt.auth.tokens import default_token_generator
77
from bolt.db.forms import ModelForm
88
from bolt.exceptions import ValidationError
99
from bolt.mail import EmailMultiAlternatives
10+
from bolt.templates import Template
1011
from bolt.utils.encoding import force_bytes
1112
from bolt.utils.http import urlsafe_base64_encode
1213

@@ -279,16 +280,16 @@ def send_mail(
279280
"""
280281
Send a bolt.mail.EmailMultiAlternatives to `to_email`.
281282
"""
282-
template = jinja.environment.from_string(subject_template_name)
283+
template = Template(subject_template_name)
283284
subject = template.render(context)
284285
# Email subject *must not* contain newlines
285286
subject = "".join(subject.splitlines())
286-
template = jinja.environment.from_string(email_template_name)
287+
template = Template(email_template_name)
287288
body = template.render(context)
288289

289290
email_message = EmailMultiAlternatives(subject, body, from_email, [to_email])
290291
if html_email_template_name is not None:
291-
template = jinja.environment.from_string(html_email_template_name)
292+
template = Template(html_email_template_name)
292293
html_email = template.render(context)
293294
email_message.attach_alternative(html_email, "text/html")
294295

bolt-htmx/bolt/htmx/jinja.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import jinja2
22
from jinja2.ext import Extension
33

4-
from bolt.jinja.extensions import InclusionTagExtension
4+
from bolt.templates.jinja.extensions import InclusionTagExtension
55

66

77
class HTMXJSExtension(InclusionTagExtension):

bolt-htmx/bolt/htmx/views.py

+7-10
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,23 @@
11
import re
22

3-
from bolt.http import HttpResponse
4-
53

64
class HTMXViewMixin:
75
htmx_template_name = ""
86

9-
def get_template_response(self, context=None) -> HttpResponse:
7+
def render_template(self):
8+
template = super().get_template()
9+
context = self.get_context()
10+
1011
if self.is_htmx_request and self.htmx_fragment_name:
1112
from .jinja import HTMXFragmentExtension
1213

13-
template = self.get_template()
14-
if context is None:
15-
context = self.get_context()
16-
rendered = HTMXFragmentExtension.render_template_fragment(
17-
template=template,
14+
return HTMXFragmentExtension.render_template_fragment(
15+
template=template._jinja_template,
1816
fragment_name=self.htmx_fragment_name,
1917
context=context,
2018
)
21-
return HttpResponse(rendered, content_type=self.content_type)
2219

23-
return super().get_template_response(context=context)
20+
return template.render(context)
2421

2522
def get_request_handler(self):
2623
if self.is_htmx_request:

bolt-importmap/bolt/importmap/jinja.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import json
22

3-
from bolt.jinja.extensions import InclusionTagExtension
43
from bolt.runtime import settings
4+
from bolt.templates.jinja.extensions import InclusionTagExtension
55

66
from .core import Importmap
77

bolt-oauth/bolt/oauth/views.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
from bolt import jinja
21
from bolt.auth.mixins import LoginRequiredMixin
32
from bolt.http import HttpResponseBadRequest, HttpResponseRedirect
3+
from bolt.templates import jinja
44
from bolt.views import View
55

66
from .exceptions import (

bolt-pages/bolt/pages/pages.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
import frontmatter
44
import pycmarkgfm
55

6-
from bolt.jinja import environment
76
from bolt.runtime import settings
7+
from bolt.templates.jinja import environment
88
from bolt.utils.functional import cached_property
99

1010

bolt-staff/bolt/admin/cards/base.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from enum import Enum
22

3-
from bolt import jinja
43
from bolt.admin.dates import DatetimeRange, DatetimeRangeAliases
4+
from bolt.templates import Template
55
from bolt.utils.text import slugify
66

77

@@ -39,8 +39,7 @@ def render(self, request, datetime_range):
3939
# If fixed, show that on the card too (I guess you could use description for this)
4040
else:
4141
self.datetime_range = datetime_range
42-
template = jinja.environment.get_template(self.template_name)
43-
return template.render(self.get_context())
42+
return Template(self.template_name).render(self.get_context())
4443

4544
@classmethod
4645
def view_name(cls) -> str:

bolt-staff/bolt/querystats/middleware.py

-12
Original file line numberDiff line numberDiff line change
@@ -86,15 +86,3 @@ def is_staff_request(request):
8686
return request.impersonator and request.impersonator.is_staff
8787

8888
return hasattr(request, "user") and request.user and request.user.is_staff
89-
90-
def process_template_response(self, request, response):
91-
# Template hasn't been rendered yet, so we can't include querystats themselves
92-
# unless we're pulling the previous page stats from the session storage
93-
if (
94-
response.context_data is not None
95-
and hasattr(_local, "querystats")
96-
and self.is_staff_request(request)
97-
):
98-
response.context_data["querystats_enabled"] = True
99-
100-
return response

bolt-staff/bolt/toolbar/jinja.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
from bolt.jinja.extensions import InclusionTagExtension
21
from bolt.runtime import settings
2+
from bolt.templates.jinja.extensions import InclusionTagExtension
33
from bolt.utils.module_loading import import_string
44

55

bolt-staff/bolt/toolbar/templates/toolbar/toolbar.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
{% endif %}
2323
</div>
2424
<div class="flex items-center space-x-4">
25-
{% if querystats_enabled|default(false) %}{% include "querystats/toolbar.html" %}{% endif %}
25+
{% include "querystats/toolbar.html" %}
2626

2727
<div class="flex items-center space-x-3 transition-all">
2828
{% include "toolbar/links.html" %}

bolt-tailwind/bolt/tailwind/jinja.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from bolt.assets.finders import APP_ASSETS_DIR
2-
from bolt.jinja.extensions import InclusionTagExtension
32
from bolt.runtime import settings
3+
from bolt.templates.jinja.extensions import InclusionTagExtension
44

55

66
class TailwindCSSExtension(InclusionTagExtension):

bolt/internal/handlers/base.py

-27
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
class BaseHandler:
1717
_view_middleware = None
18-
_template_response_middleware = None
1918
_exception_middleware = None
2019
_middleware_chain = None
2120

@@ -26,7 +25,6 @@ def load_middleware(self):
2625
Must be called after the environment is fixed (see __call__ in subclasses).
2726
"""
2827
self._view_middleware = []
29-
self._template_response_middleware = []
3028
self._exception_middleware = []
3129

3230
get_response = self._get_response
@@ -61,10 +59,6 @@ def load_middleware(self):
6159
0,
6260
self.adapt_method_mode(mw_instance.process_view),
6361
)
64-
if hasattr(mw_instance, "process_template_response"):
65-
self._template_response_middleware.append(
66-
self.adapt_method_mode(mw_instance.process_template_response),
67-
)
6862
if hasattr(mw_instance, "process_exception"):
6963
# The exception-handling stack is still always synchronous for
7064
# now, so adapt that way.
@@ -145,27 +139,6 @@ def _get_response(self, request):
145139
# Complain if the view returned None (a common error).
146140
self.check_response(response, callback)
147141

148-
# If the response supports deferred rendering, apply template
149-
# response middleware and then render the response
150-
if hasattr(response, "render") and callable(response.render):
151-
for middleware_method in self._template_response_middleware:
152-
response = middleware_method(request, response)
153-
# Complain if the template response middleware returned None
154-
# (a common error).
155-
self.check_response(
156-
response,
157-
middleware_method,
158-
name="{}.process_template_response".format(
159-
middleware_method.__self__.__class__.__name__
160-
),
161-
)
162-
try:
163-
response = response.render()
164-
except Exception as e:
165-
response = self.process_exception_by_middleware(e, request)
166-
if response is None:
167-
raise
168-
169142
return response
170143

171144
def resolve_request(self, request):

bolt/jinja/context.py

-15
This file was deleted.

bolt/runtime/global_settings.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -196,4 +196,4 @@
196196
#############
197197

198198
JINJA_LOADER = "jinja2.loaders.FileSystemLoader"
199-
JINJA_ENVIRONMENT = "bolt.jinja.defaults.create_default_environment"
199+
JINJA_ENVIRONMENT = "bolt.templates.jinja.defaults.create_default_environment"

bolt/templates/__init__.py

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from .core import Template, TemplateFileMissing
2+
3+
__all__ = [
4+
"Template",
5+
"TemplateFileMissing",
6+
]

bolt/templates/core.py

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import jinja2
2+
3+
from .jinja import environment
4+
5+
6+
class TemplateFileMissing(Exception):
7+
pass
8+
9+
10+
class Template:
11+
def __init__(self, filename: str) -> None:
12+
self.filename = filename
13+
14+
try:
15+
self._jinja_template = environment.get_template(filename)
16+
except jinja2.TemplateNotFound:
17+
raise TemplateFileMissing(f"Template file {filename} not found")
18+
19+
def render(self, context: dict) -> str:
20+
return self._jinja_template.render(context)
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

bolt/utils/decorators.py

+2-16
Original file line numberDiff line numberDiff line change
@@ -122,22 +122,8 @@ def _wrapper_view(request, *args, **kwargs):
122122
if result is not None:
123123
return result
124124
raise
125-
if hasattr(response, "render") and callable(response.render):
126-
if hasattr(middleware, "process_template_response"):
127-
response = middleware.process_template_response(
128-
request, response
129-
)
130-
# Defer running of process_response until after the template
131-
# has been rendered:
132-
if hasattr(middleware, "process_response"):
133-
134-
def callback(response):
135-
return middleware.process_response(request, response)
136-
137-
response.add_post_render_callback(callback)
138-
else:
139-
if hasattr(middleware, "process_response"):
140-
return middleware.process_response(request, response)
125+
if hasattr(middleware, "process_response"):
126+
return middleware.process_response(request, response)
141127
return response
142128

143129
return _wrapper_view

bolt/views/base.py

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ def view(request, *args, **kwargs):
5555

5656
def get_request_handler(self) -> callable:
5757
"""Return the handler for the current request method."""
58+
5859
if not self.request.method:
5960
raise AttributeError("HTTP method is not set")
6061

bolt/views/forms.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def form_invalid(self, form: "BaseForm") -> HttpResponse:
5656
**self.get_context(),
5757
"form": form,
5858
}
59-
return self.get_template_response(context)
59+
return self.get_template().render(context)
6060

6161
def get_context(self) -> dict:
6262
"""Insert the form into the context dict."""

bolt/views/objects.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class ObjectTemplateViewMixin:
1010

1111
def get(self) -> HttpResponse:
1212
self.load_object()
13-
return self.get_template_response()
13+
return self.render_template()
1414

1515
def load_object(self) -> None:
1616
try:
@@ -191,7 +191,7 @@ class ListView(TemplateView):
191191

192192
def get(self) -> HttpResponse:
193193
self.objects = self.get_queryset()
194-
return self.get_template_response()
194+
return super().get()
195195

196196
def get_queryset(self): # Intentionally untyped... subclasses must override this.
197197
raise NotImplementedError(

0 commit comments

Comments
 (0)