Last active
September 11, 2024 19:44
-
-
Save geoffrey-eisenbarth/e521497e032514791f7e29acd01daf7c to your computer and use it in GitHub Desktop.
Django Middleware for django-template-partials
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class HtmxPartialTemplateMiddleware: | |
"""Adds support for rendering partials with django-template-partials. | |
NOTES | |
----- | |
In order for this middleware to work properly, the following conditions must be met: | |
1) django-template-partials must be installed | |
2) Each template must have a partial defined directly in it with a name that coincides | |
with the HTML id of the element being swapped out. Since django-template-partials does | |
not support rendering partials defined in parent templates, you must be careful when | |
using Django's {% extends %} syntax. | |
3) One nice benefit of this method, is if you create partials surrounding your <forms> and | |
then set the `HX-Retarget` to e.g., `#form` in a view's `form_invalid()` method, then the | |
middleware will render the form errors and `HX-Retarget` will replace the submitted form | |
with validated form, showing the errors. | |
""" | |
DEFAULT_PARTIAL_NAME = 'main' | |
def __init__(self, get_response) -> None: | |
self.get_response = get_response | |
def __call__(self, request: HttpRequest) -> HttpResponse: | |
response = self.get_response(request) | |
if request.htmx and (response.status_code == 302): | |
response = HttpResponseClientRedirect(response.url) | |
return response | |
def process_template_response(self, request, response): | |
if request.htmx: | |
if retarget_id := response.get('HX-Retarget'): | |
partial_name = retarget_id.strip('#') | |
else: | |
partial_name = request.htmx.target or self.DEFAULT_PARTIAL_NAME | |
response.template_name = [ | |
f'{template_name}#{partial_name}' | |
if '#' not in template_name | |
else template_name | |
for template_name in response.template_name | |
] | |
return response |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Some notes about
django-template-partials
and this middleware:django-render-block
, although a middleware like this would not work as well sincedjango-render-block
does not tie into the template rendering system (so a middleware withprocess_template_response
would not work, since the view would not being returning a TemplateResponse object). It's probably best to usedjango-render-block
if you're using function based views.I'm by no means an expert at this stuff, simply documenting what I've learned trying to combine HTMX and class-based views. If you have any thoughts, suggestions, questions, or enhancements, I'd love to hear them.