You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django+HTMX表单问题:验证失败后DOM未更新错误提示

HTMX + Django 表单异步提交验证错误不显示问题排查与解决

问题现象

使用HTMX与Django实现表单无刷新提交时,表单验证失败后后端正确返回contact_messages.html模板内容(可在网络面板查看到),但页面中div#contact-messages元素并未更新,无法显示错误提示。同步提交时Django表单验证功能正常。

代码片段

视图代码

class ContactView(FormView):
    template_name = 'contact/contact.html'
    form_class = ContactForm
    success_url = reverse_lazy('contact')

    def form_valid(self, form):        
        messages.success(self.request, "Your message has been sent. We will be in touch with you as soon as possible.")
        return redirect(self.success_url + '#contact-section')

    def form_invalid(self, form):
        messages.error(
            self.request,
            "There were some errors in your submission. Please review the highlighted fields and try again",
            extra_tags="danger")

        if self.request.headers.get("HX-Request"):
            return render(self.request, "contact/contact_messages.html", {"form": form}, content_type="text/html", status=400)

        return super().form_invalid(form)

contact.html 表单代码

<form id="contact-form" method="post" hx-post="{% url 'contact' %}"
     hx-target="#contact-messages"  hx-swap="innerHTML" novalidate>
    {% csrf_token %}

    <div id='contact-messages'>
        {% include 'contact/contact_messages.html' %}
    </div>

    <div class="form-group mb-0">
        <button class=" btn btn-primary w-100">
            <span>Send Message</span>
        </button>
    </div>
</form>

contact_messages.html 模板代码

% if messages %}
    {% for message in messages %}
        <div class="alert alert-{{ message.tags }}" role="alert">
            {{ message }}
            <button type="button" class="close" data-dismiss="alert" aria-label="Close">
                <span aria-hidden="true">&times;</span></button>
        </div>
    {% endfor %}
{% endif %}

{% for field in form %}
    <div class="form-group">
        {{ field }}
        {% if form.errors %}
            <div class="invalid-feedback d-block">
                {% for error in field.errors %}
                    {{ error }}
                {% endfor %}
            </div>
        {% endif %}
    </div>
{% endfor %}

解决方案

1. 修复HTMX不处理错误响应的问题

HTMX默认仅对2xx状态码的响应执行内容替换,你的代码返回了400状态码,会被判定为错误响应,默认不触发更新。

解决方式二选一:

  • 修改响应状态码(推荐):将HX请求的响应状态码改为200
    if self.request.headers.get("HX-Request"):
        return render(self.request, "contact/contact_messages.html", {"form": form}, content_type="text/html", status=200)
    
  • 配置HTMX处理错误响应:在表单上添加hx-swap-error="innerHTML"属性
    <form id="contact-form" method="post" hx-post="{% url 'contact' %}"
          hx-target="#contact-messages" hx-swap="innerHTML" hx-swap-error="innerHTML" novalidate>
    

2. 补全模板上下文缺失的messages变量

你在contact_messages.html中使用了messages变量,但HX请求的渲染上下文未传入该变量,导致消息提示无法显示。

修改视图代码,手动传入messages:

from django.contrib.messages import get_messages

def form_invalid(self, form):
    messages.error(
        self.request,
        "There were some errors in your submission. Please review the highlighted fields and try again",
        extra_tags="danger")

    if self.request.headers.get("HX-Request"):
        context = {
            "form": form,
            "messages": get_messages(self.request)
        }
        return render(self.request, "contact/contact_messages.html", context, content_type="text/html", status=200)

    return super().form_invalid(form)

3. 修复模板语法错误

contact_messages.html第一行缺少起始的{,导致模板渲染异常,修正为:

{% if messages %}
    {% for message in messages %}
        <div class="alert alert-{{ message.tags }}" role="alert">
            {{ message }}
            <button type="button" class="close" data-dismiss="alert" aria-label="Close">
                <span aria-hidden="true">&times;</span></button>
        </div>
    {% endfor %}
{% endif %}

{% for field in form %}
    <div class="form-group">
        {{ field }}
        {% if field.errors %}
            <div class="invalid-feedback d-block">
                {% for error in field.errors %}
                    {{ error }}
                {% endfor %}
            </div>
        {% endif %}
    </div>
{% endfor %}

同时将{% if form.errors %}改为{% if field.errors %},避免无错误字段也显示错误容器。


内容的提问来源于stack exchange,提问作者Eric Gutierrez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 13:40:08