一键导入
django-htmx
Build modern dynamic web applications with Django and htmx - partial rendering, HTMX-specific responses, and seamless frontend integration
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Build modern dynamic web applications with Django and htmx - partial rendering, HTMX-specific responses, and seamless frontend integration
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Develop C++ plugins for Kate text editor using KTextEditor Framework, CMake with ECM, Qt threading, and KDE plugin architecture
Develop plugins, tools, and extensions for OpenCode AI coding agent with MCP, LSP integration, custom tools, and SDK usage
Django security - CSRF protection, authentication, sessions, login/logout, password handling, middleware, protected views
Python testing framework with powerful fixtures, parametrization, extensive plugin ecosystem, and support for async, Django, Flask testing
Python SQL toolkit and ORM with expressive query API, relationship mapping, async support, and Alembic migrations
Common Rust development pitfalls: frequent compiler errors, struct constructor patterns, test organization, and coverage enforcement for reliable codebases.
| name | django-htmx |
| description | Build modern dynamic web applications with Django and htmx - partial rendering, HTMX-specific responses, and seamless frontend integration |
| metadata | {"author":"mte90","version":"1.0.0","tags":["django","htmx","python","web","frontend","partial-rendering","ajax"]} |
Django-htmx provides seamless integration between Django and htmx for building modern, dynamic web applications without writing complex JavaScript.
pip install django-htmx
Add to INSTALLED_APPS:
INSTALLED_APPS = [
...
"django_htmx",
]
Add the middleware:
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django_htmx.middleware.HtmxMiddleware", # Add this
...
]
The middleware adds request.htmx to detect htmx requests:
from django.shortcuts import render
def my_view(request):
if request.htmx:
template_name = "partial.html"
else:
template_name = "full.html"
return render(request, template_name)
The request.htmx object provides these attributes:
request.htmx - Boolean, True if request is from htmxrequest.htmx.boosted - True if request is from boosted element (hx-boost)request.htmx.current_url - Current URL in browser from HX-Current-URL headerrequest.htmx.current_url_abs_path - Absolute path form of current_urlrequest.htmx.history_restore_request - True if request is for history restorationrequest.htmx.target - Target element ID from HX-Target headerrequest.htmx.trigger - Trigger element ID from HX-Trigger headerrequest.htmx.trigger_name - Trigger element name from HX-Trigger-Name headerrequest.htmx.prompt - User response to hx-prompt attributerequest.htmx.triggering_event - Deserialized JSON from event-header extensionLoad and use in templates:
{% load django_htmx %}
<!DOCTYPE html>
<html>
<head>
{% htmx_script %}
</head>
<body hx-headers='{"x-csrftoken": "{{ csrf_token }}"}'>
...
</body>
</html>
{% load django_htmx %}
<!doctype html>
<html>
<head>
{% htmx_script %}
</head>
<body hx-headers='{"x-csrftoken": "{{ csrf_token }}"}'>
...
</body>
</html>
Use minified=False for debugging:
{% htmx_script minified=False %}
from jinja2 import Environment
from django_htmx.jinja import htmx_script
def environment(**options):
env = Environment(**options)
env.globals.update({"htmx_script": htmx_script})
return env
{{ htmx_script() }}
Triggers a client-side redirect (HX-Redirect header):
from django_htmx.http import HttpResponseClientRedirect
def sensitive_view(request):
if not sudo_mode.active(request):
next_url = request.htmx.current_url_abs_path or ""
return HttpResponseClientRedirect(f"/activate-sudo/?next={next_url}")
...
Triggers a page reload (HX-Refresh header):
from django_htmx.http import HttpResponseClientRefresh
def partial_table_view(request):
if page_outdated(request):
return HttpResponseClientRefresh()
...
Makes htmx do a client-side "boosted" request (HX-Location header):
from django_htmx.http import HttpResponseLocation
def wait_for_completion(request, action_id):
...
if action.completed:
return HttpResponseLocation(f"/action/{action.id}/completed/")
...
Stops polling when using hx-trigger="every":
from django_htmx.http import HttpResponseStopPolling
def my_pollable_view(request):
if event_finished():
return HttpResponseStopPolling()
...
Or use the constant directly:
from django_htmx.http import HTMX_STOP_POLLING
from django.shortcuts import render
def my_pollable_view(request):
if event_finished():
return render(request, "event-finished.html", status=HTMX_STOP_POLLING)
...
Push a new URL to the browser history:
from django_htmx.http import push_url
def leaf(request, leaf_id):
...
if leaf is None:
response = branch(request, branch=leaf.branch)
return push_url(response, f"/branch/{leaf.branch.id}")
...
Replace the current URL in browser history:
from django_htmx.http import replace_url
def dashboard(request):
...
response = render(request, "dashboard.html", ...)
return replace_url(response, "/dashboard/")
Override the swap method:
from django.shortcuts import render
from django_htmx.http import reswap
def employee_table_row(request):
...
response = render(...)
if employee.is_boss:
reswap(response, "afterbegin")
return response
Override the target element:
from django.shortcuts import render
from django.views.decorators.http import require_POST
from django_htmx.http import retarget
@require_POST
def add_widget(request):
...
if form.is_valid():
response = render(request, "widget-table.html", ...)
return retarget(response, "#widgets")
return render(request, "widget-table-row.html", ...)
Override the content selection:
from django_htmx.http import reselect
def update_table(request):
response = render(request, "table.html", ...)
return reselect(response, "tbody")
Trigger client-side events:
from django.shortcuts import render
from django_htmx.http import trigger_client_event
def end_of_long_process(request):
response = render(request, "end-of-long-process.html")
return trigger_client_event(
response,
"showConfetti",
{"colours": ["purple", "red", "pink"]},
after="swap", # "receive", "settle", or "swap"
)
Use django-template-partials for efficient partial rendering:
pip install django-template-partials
{% extends "_base.html" %}
{% load partials %}
{% block main %}
{% partialdef country-table inline %}
<table id="country-data">
...
</table>
{% endpartialdef %}
{% endblock main %}
In views:
def country_listing(request):
template_name = "countries.html"
if request.htmx:
template_name += "#country-table"
countries = Country.objects.all()
return render(request, template_name, {"countries": countries})
def partial_rendering(request):
if request.htmx:
base_template = "_partial.html"
else:
base_template = "_base.html"
return render(request, "page.html", {"base_template": base_template})
{% extends base_template %}
{% block main %}
...
{% endblock %}
Always include CSRF token in htmx requests:
<body hx-headers='{"x-csrftoken": "{{ csrf_token }}"}'>
Add appropriate Vary headers for cacheable responses:
from django.shortcuts import render
from django.views.decorators.cache import cache_control
from django.views.decorators.vary import vary_on_headers
@cache_control(max_age=300)
@vary_on_headers("HX-Request")
def my_view(request):
if request.htmx:
template_name = "partial.html"
else:
template_name = "complete.html"
return render(request, template_name, ...)
Download extensions locally (avoid CDNs):
curl -L https://unpkg.com/htmx-ext-ws/dist/ws.min.js -o static/htmx-ext-ws.min.js
{% load django_htmx static %}
<!doctype html>
<html>
<head>
{% htmx_script %}
<script src="{% static 'htmx-ext-ws.min.js' %}" defer></script>
</head>
...
</html>
For type-checking, extend HttpRequest:
from django.http import HttpRequest as HttpRequestBase
from django_htmx.middleware import HtmxDetails
class HttpRequest(HttpRequestBase):
htmx: HtmxDetails