Django Live Search with HTMX

Adi Ramadhan
3 min readMay 22, 2024

Reference https://www.djangoproject.com/ and https://htmx.org/

Django live search with HTMX

Note: Django Admin in story used for add movies data.

Step 1: Preparation, Create Django Project, Inital Migration
create virtualenv: virtualenv venv
start virtualenv: venv/Scripts/activate
install Django in virtualenv: pip install django==4.2
Create Django: django-admin startproject myproject
Go to myproject folder: cd myproject
Initial Migration: python manage.py migrate

Step 2: Project Setting: Register Apps, Set Templates Folder (myproject/settings.py)

...

INSTALLED_APPS = [
...
'myapp', #updated
]

...

TEMPLATES = [
...
'DIRS': [Path(BASE_DIR, 'templates')], #updated
...
]


...

Step 3: Add Model in myapp/models.py

from django.db import models

# Create your models here.
class Movie(models.Model):
title = models.CharField(max_length=100)
description = models.TextField(max_length=1000)
year = models.IntegerField(default=2000)

Step 4: Register Model in Django Admin

from django.contrib import admin
from .models import Movie


class MovieAdmin(admin.ModelAdmin):
list_display = ('title', 'description', 'year')

admin.site.register(Movie, MovieAdmin)

Step 5: Makemigrations and Migrate
Make migrations: python manage.py makemigrations
Migrate: python manage.py migrate

Step 6: Create HTML Files in Templates Folder

Create templates folder in main app

Create templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Title</title>
</head>
<body>

<input type="search"
name="keyword" placeholder="Search movies..."
hx-post="{% url 'list' %}"
hx-trigger="load, input changed delay:500ms, keyword"
hx-target="#search-results"
hx-indicator=".htmx-indicator"
hx-headers='{"X-CSRFToken":"{{ csrf_token }}"}'
>
<br>
<span class="htmx-indicator" >
Searching...
</span>
<div id="search-results">

</div>

<script src="https://unpkg.com/htmx.org@1.9.12"></script>
</body>
</html>

Create templates/list.html

{% if movies %}
{% for movie in movies %}
<h3>{{movie.title}} ({{movie.year}})</h3>
<p>{{movie.description }}</p>
{% endfor %}
{% else %}
<p>No result</p>
{% endif %}

Step 7: Create Function Views myapp/views.py

from django.shortcuts import render
from .models import Movie

# Create your views here.
def index(request):
template = 'index.html'
extra_context = {}
return render(request, template, extra_context)

def list(request):
template = 'list.html'
keyword = request.POST.get("keyword")
movies = Movie.objects.filter(title__icontains=keyword) #search title by keyword
extra_context = {'movies': movies}
return render(request, template, extra_context)

Step 8: Setup URLS

Create myapp/urls.py


from django.urls import path
from . import views

urlpatterns = [
path("", views.index, name="index"),
path("list/", views.list, name="list"),
]

Update myproject/urls.py

from django.contrib import admin
from django.urls import path, include #updated

urlpatterns = [
path('admin/', admin.site.urls),
path('', include('myapp.urls')), #updated
]

Step 9: Run Server and Testing

Run Server: python manage.py runserver
Testing:

a. Login in Django Admin and add movies http://127.0.0.1:8000/admin

b. Open http://127.0.0.1:8000/

--

--