Getting Started#

HTMX is a modern JavaScript library that allows you to access AJAX, CSS transitions, WebSockets, and Server-Sent Events directly in HTML, without writing JavaScript. When paired with Django, it creates a powerful combination that simplifies building dynamic web applications.

๐Ÿ‘‰ New to App-Generator? Sign IN with GitHub or Generate Web Apps in no time (free service).

Set Up Environment#

First, letโ€™s create a basic development environment:

# Create a virtual environment
python -m venv venv

# Activate the virtual environment
# For Windows:
venv\Scripts\activate
# For macOS/Linux:
source venv/bin/activate

# Install Django
pip install django

# Create a new Django project
django-admin startproject htmx_demo

# Navigate to your project
cd htmx_demo

# Create an app
python manage.py startapp demo

Configure Your Django Project#

Add your app to the project settings:

# htmx_demo/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'demo',  # Add your app here
]

Create a Basic Model#

# demo/models.py
from django.db import models

class Task(models.Model):
    title = models.CharField(max_length=100)
    completed = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title

Run migrations:

python manage.py makemigrations
python manage.py migrate

Set Up Templates#

Create a base template:

mkdir -p demo/templates/demo
<!-- demo/templates/demo/base.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Django + HTMX Demo</title>

    <!-- Include HTMX -->
    <script src="https://unpkg.com/htmx.org@1.9.10"></script>

    <style>
        body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
        .task { padding: 10px; margin: 5px 0; border: 1px solid #ddd; border-radius: 4px; }
        .completed { text-decoration: line-through; background-color: #f8f8f8; }
        button { cursor: pointer; }
    </style>
</head>
<body>
    <h1>Django + HTMX Task Manager</h1>

    {% block content %}{% endblock %}
</body>
</html>

Create Views and Templates#

Create a view for the task list:

# demo/views.py
from django.shortcuts import render
from django.http import HttpResponse
from .models import Task

def task_list(request):
    tasks = Task.objects.all().order_by('-created_at')
    return render(request, 'demo/task_list.html', {'tasks': tasks})

def add_task(request):
    title = request.POST.get('title')
    task = Task.objects.create(title=title)
    return render(request, 'demo/partials/task.html', {'task': task})

def toggle_task(request, pk):
    task = Task.objects.get(pk=pk)
    task.completed = not task.completed
    task.save()
    return render(request, 'demo/partials/task.html', {'task': task})

def delete_task(request, pk):
    Task.objects.get(pk=pk).delete()
    return HttpResponse("")

Create templates for the task list:

<!-- demo/templates/demo/task_list.html -->
{% extends "demo/base.html" %}

{% block content %}
    <!-- Add Task Form -->
    <form hx-post="{% url 'add_task' %}" hx-target="#task-list" hx-swap="afterbegin">
        {% csrf_token %}
        <input type="text" name="title" placeholder="Add a new task..." required>
        <button type="submit">Add</button>
    </form>

    <!-- Task List -->
    <div id="task-list">
        {% for task in tasks %}
            {% include "demo/partials/task.html" %}
        {% endfor %}
    </div>
{% endblock %}

Create a partial template for individual tasks:

<!-- demo/templates/demo/partials/task.html -->
<div class="task {% if task.completed %}completed{% endif %}" id="task-{{ task.id }}">
    <input type="checkbox"
          {% if task.completed %}checked{% endif %}
          hx-post="{% url 'toggle_task' task.id %}"
          hx-target="#task-{{ task.id }}"
          hx-swap="outerHTML">
    {{ task.title }}
    <button hx-delete="{% url 'delete_task' task.id %}"
            hx-target="#task-{{ task.id }}"
            hx-swap="outerHTML">Delete</button>
</div>

Set Up URLs (routing)#

# demo/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.task_list, name='task_list'),
    path('add/', views.add_task, name='add_task'),
    path('toggle/<int:pk>/', views.toggle_task, name='toggle_task'),
    path('delete/<int:pk>/', views.delete_task, name='delete_task'),
]
# htmx_demo/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('demo.urls')),
]

Run Project#

python manage.py runserver

Visit http://127.0.0.1:8000/ in your browser to see your app in action!

Understanding The Concept#

HTMX Attributes:#

  • hx-post: Makes a POST request to the specified URL

  • hx-get: Makes a GET request to the specified URL

  • hx-delete: Makes a DELETE request to the specified URL

  • hx-target: Specifies where to insert the response HTML

  • hx-swap: Defines how the response should be inserted (e.g., innerHTML, outerHTML, afterbegin)

  • hx-trigger: Defines when the request should be triggered (default is based on the elementโ€™s natural event)

HTMX Flow:#

  • User interacts with an element with HTMX attributes

  • HTMX sends an AJAX request to the server

  • Server returns HTML fragment

  • HTMX inserts the HTML fragment into the target element

For developers familiar with Djangoโ€™s templating system, HTMX feels like a natural extension that brings modern interactivity without the overhead of a complex JavaScript ecosystem.

Rocket HTMX#

Django Rocket HTMX is an open-source starter built with basic modules, authentication, data tables, charts, API and HTMX support. The product UI is styled with Flowbite, an open source collection of UI components built with the utility classes from Tailwind CSS.

Features#

  • Simple, Easy-to-Extend codebase

  • Styling: Flowbite/Tailwind

  • Extended User Model

  • ApexJS Charts

  • DataTables via HTMX

  • API

  • DB Persistence: SQLite (default), can be used with MySql, PgSql

  • Docker

  • CI/CD integration for Render

Django Rocket HTMX - Open-source Starter powered by HTMX and Tailwind