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

如何在Django 4.2.9表单验证失败时为输入框添加额外类

Django 4.2.9:表单验证失败时为输入字段添加CSS类

问题描述

使用Django 4.2.9,需实现表单验证失败时,为text输入字段追加is-invalid CSS类。目前已能设置常规场景的类,但不知如何处理验证错误的情况。

现有ItemForm代码:

class ItemForm(forms.models.ModelForm):
    class Meta:
        model = Item
        fields = ("text", )
        widgets = {
            "text": forms.widgets.TextInput(
                attrs={
                    "placeholder": "Enter a to-do item",
                    "class": "form-control form-control-lg",
                }
            ),
        }
        error_messages = {"text": {"required": EMPTY_ITEM_ERROR}}

    def save(self, for_list):
        self.instance.list = for_list
        return super().save()

期望验证失败时,text输入框的class变为form-control form-control-lg is-invalid,当前表单渲染后的HTML:

<form method="POST" action="/lists/8/">
    <input type="text" name="text" value="Buy wellies" placeholder="Enter a to-do item" class="form-control form-control-lg" required id="id_text">
    <input type="hidden" name="csrfmiddlewaretoken" value="vcojkMtz3GeonURczjMwIsbsDPQUbeKgrXrPIxZY4jIJSfuUKKGVgaj7wLQBatsd">                        
    <div class="invalid-feedback"><ul class="errorlist"><li>You&#x27;ve already got this in your list</li></ul></div>
                        
</form>

解决方案

方法1:重写表单__init__方法

在表单初始化阶段检查字段错误,动态追加CSS类:

class ItemForm(forms.models.ModelForm):
    class Meta:
        model = Item
        fields = ("text", )
        widgets = {
            "text": forms.widgets.TextInput(
                attrs={
                    "placeholder": "Enter a to-do item",
                    "class": "form-control form-control-lg",
                }
            ),
        }
        error_messages = {"text": {"required": EMPTY_ITEM_ERROR}}

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 检查text字段是否存在验证错误
        if self.errors.get('text'):
            current_classes = self.fields['text'].widget.attrs.get('class', '')
            self.fields['text'].widget.attrs['class'] = f"{current_classes} is-invalid"

    def save(self, for_list):
        self.instance.list = for_list
        return super().save()

方法2:模板层面直接处理

无需修改表单类,在模板渲染时判断字段状态并添加类:

<form method="POST" action="/lists/8/">
    {% csrf_token %}
    {% with field=form.text %}
        <input 
            type="text" 
            name="{{ field.name }}" 
            value="{{ field.value|default:'' }}" 
            placeholder="Enter a to-do item" 
            class="form-control form-control-lg {% if field.errors %}is-invalid{% endif %}" 
            required 
            id="{{ field.id_for_label }}">
    {% endwith %}
    {% if form.text.errors %}
        <div class="invalid-feedback">
            {{ form.text.errors }}
        </div>
    {% endif %}
</form>

方法3:自定义Widget类

如果多个表单需要该功能,可封装通用Widget复用:

class CustomTextInput(forms.TextInput):
    def get_context(self, name, value, attrs):
        context = super().get_context(name, value, attrs)
        # 获取表单实例,检查当前字段是否有错误
        form_instance = context['widget']['form']
        if form_instance and form_instance.errors.get(name):
            current_classes = context['widget']['attrs'].get('class', '')
            context['widget']['attrs']['class'] = f"{current_classes} is-invalid"
        return context

# 在表单中使用自定义Widget
class ItemForm(forms.models.ModelForm):
    class Meta:
        model = Item
        fields = ("text", )
        widgets = {
            "text": CustomTextInput(
                attrs={
                    "placeholder": "Enter a to-do item",
                    "class": "form-control form-control-lg",
                }
            ),
        }
        error_messages = {"text": {"required": EMPTY_ITEM_ERROR}}

    def save(self, for_list):
        self.instance.list = for_list
        return super().save()

内容的提问来源于stack exchange,提问作者Marco Frost

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 05:33:35