Form and View mixins for HTMX/partials

This commit is contained in:
Tobias Kunze 2025-03-20 08:26:13 +01:00
parent dcbf98f829
commit ecf4052819
2 changed files with 51 additions and 0 deletions

View file

@ -0,0 +1,15 @@
class HtmxMixin:
"""
Form mixin that retains only a single field when specified.
Useful when sending single fields with htmx.
"""
def __init__(self, *args, **kwargs):
self.single_field = kwargs.pop("single_field", None)
super().__init__(*args, **kwargs)
if self.single_field and self.single_field in self.fields:
field = self.fields[self.single_field]
self.fields.clear()
self.fields[self.single_field] = field

View file

@ -0,0 +1,36 @@
from django.utils.functional import cached_property
from django.views.generic import TemplateView
class HtmxMixin(TemplateView):
fragments = []
@cached_property
def is_htmx(self):
return self.request.headers.get("HX-Request")
def _get_fragment(self):
if self.request.method == "POST":
fragment = self.request.POST.get("fragment")
else:
fragment = self.request.GET.get("fragment")
if fragment and fragment in self.fragments:
return fragment
def get_template_names(self):
template_names = super().get_template_names()
if self.is_htmx and (fragment := self._get_fragment()):
return [f"{template_names[0]}#{fragment}"]
return template_names
def get_form_kwargs(self):
result = super().get_form_kwargs()
if self.is_htmx and (field_name := self.request.POST.get("hx-single-field")):
result["single_field"] = field_name
return result
def form_valid(self, form):
result = super().form_valid(form)
if self.is_htmx and self._get_fragment():
return self.get(self.request, *self.args, **self.kwargs)
return result