HTMX#

See django-htmx [1] for detailed information about using django-htmx in your django-cookiecutter project.

Class Base Views#

django-cookiecutter has used a similar approach to Class-Based Views as the Django standard libray. Importing HTMX enabled Generic Views is as straight forward as Django but comes from django-cookiecutter core. The htmx views are mixins using htmx and django views.

HTMX#

All of Django Generic Edit, List and Detail Views are available from core.views.generic.

 1from core.views.generic.base import HtmxTemplateView
 2
 3from core.views.generic.detail import HtmxDetailView
 4from core.views.generic.edit import (
 5    HtmxCreateView,
 6    HtmxDeleteView,
 7    HtmxFormView,
 8    HtmxUpdateView,
 9)
10from core.views.generic.list import HtmxListView
11
12__all__ = [
13    "HtmxCreateView",
14    "HtmxDeleteView",
15    "HtmxDetailView",
16    "HtmxFormView",
17    "HtmxListView",
18    "HtmxTemplateView",
19    "HtmxUpdateView",
20    "HtmxGenericViewError",
21]
22
23
24class HtmxGenericViewError(Exception):
25    """A problem in a generic view."""
26
27    pass

A simple htmx create view.

 1from core.views.generic import HtmxCreateView
 2from .forms import YourForm
 3from .models import YourModel
 4
 5class YourHtmxCreateView(HtmxCreateView):
 6    """Your HTMX Create View"""
 7    form_class = YourForm
 8    model = YourModel
 9    htmx_template_name = "your/htmx/partial/template.html"
10    template_name = "your/standard/django/template.html"
11    success_url = reverse_lazy("your_success_url")
12
13    def your_code_here(self):

Django#

All of Django Generic Edit, List and Detail Views are still available from Django standard library if you prefer to use those in some cases.

 1from django.views.generic import CreateView
 2from .forms import YourForm
 3from .models import YourModel
 4
 5class YourCreateView(CreateView):
 6    """Your Django Create View"""
 7    form_class = YourForm
 8    model = YourModel
 9    template_name = "your/standard/django/template.html"
10    success_url = reverse_lazy("your_success_url")
11
12    def your_code_here(self):

HTMX Function View#

An example taken from django-htmx examples [2].

 1@require_GET
 2def partial_rendering(request: HttpRequest) -> HttpResponse:
 3    # Standard Django pagination
 4    page_num = request.GET.get("page", "1")
 5    page = Paginator(object_list=people, per_page=10).get_page(page_num)
 6
 7    # The htmx magic - use a different, minimal base template for htmx
 8    # requests, allowing us to skip rendering the unchanging parts of the
 9    # template.
10    if request.htmx:
11        base_template = "_partial.html"
12    else:
13        base_template = "_base.html"
14
15    return render(
16        request,
17        "partial-rendering.html",
18        {
19            "base_template": base_template,
20            "page": page,
21        },
22    )

HTMX CSRF in HTML#

HTMX uses HTTP methods other than GET. Django expects a CSRF security token in the request; otherwise, Django will respond to the request with a 403 Forbidden status code.

Htmx looks to parent elements for additional attributes; you can apply the CSRF token for HTMX methods globally by including the hx-headers in the body tag, as shown below.

This CSRF method is taken from Matt Laymans blog How To Use Htmx In Django [3]. See Matt’s blog for another technique to add CSRF tokens.

 1<html>
 2
 3    <head><title>HTML Base file</title></head>
 4
 5    <body hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'>
 6        {% block main %}{% endblock %}
 7        <script src="https://unpkg.com/htmx.org@1.1.0"></script>
 8    </body>
 9
10</html>

Further Reading#

A fantastic list of htmx examples on htmx.org [4].

An excellent YouTube Django HTMX series by BUGBYTES [5].


Footnotes