Coverage for /Users/davegaeddert/Developer/dropseed/plain/plain-htmx/plain/htmx/views.py: 38%
39 statements
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-23 11:16 -0600
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-23 11:16 -0600
1import re
3from plain.utils.cache import patch_vary_headers
5from .templates import render_template_fragment
8class HTMXViewMixin:
9 htmx_template_name = ""
11 def render_template(self):
12 template = self.get_template()
13 context = self.get_template_context()
15 if self.is_htmx_request and self.htmx_fragment_name:
16 return render_template_fragment(
17 template=template._jinja_template,
18 fragment_name=self.htmx_fragment_name,
19 context=context,
20 )
22 return template.render(context)
24 def get_response(self):
25 response = super().get_response()
26 # Tell browser caching to also consider the fragment header,
27 # not just the url/cookie.
28 patch_vary_headers(
29 response, ["HX-Request", "Plain-HX-Fragment", "Plain-HX-Action"]
30 )
31 return response
33 def get_request_handler(self):
34 if self.is_htmx_request:
35 # You can use an htmx_{method} method on views
36 # (or htmx_{method}_{action} for specific actions)
37 method = f"htmx_{self.request.method.lower()}"
38 if self.htmx_action_name:
39 method += f"_{self.htmx_action_name}"
41 if handler := getattr(self, method, None):
42 return handler
44 return super().get_request_handler()
46 def get_template_names(self):
47 # TODO is this part necessary anymore?? can I replace those with fragments now?
48 if self.is_htmx_request:
49 if self.htmx_template_name:
50 return [self.htmx_template_name]
52 default_template_names = super().get_template_names()
53 return (
54 [
55 re.sub(r"\.html$", "_htmx.html", template_name)
56 for template_name in default_template_names
57 ]
58 + default_template_names
59 ) # Fallback to the defaults so you don't need _htmx.html
61 return super().get_template_names()
63 @property
64 def is_htmx_request(self):
65 return self.request.headers.get("HX-Request") == "true"
67 @property
68 def htmx_fragment_name(self):
69 # A custom header that we pass with the {% htmxfragment %} tag
70 return self.request.headers.get("Plain-HX-Fragment", "")
72 @property
73 def htmx_action_name(self):
74 return self.request.headers.get("Plain-HX-Action", "")