[Django]-Adding a class 'is-invalid' to input form in Django

2👍

Create a file, yourapp_template-filters.py
and then place it in templatetags folder in your app:

from django import template
register = template.Library()


@register.filter(name='add_attr')
def add_attribute(field, css):
    attrs = {}
    definition = css.split(',')

    for d in definition:
        if ':' not in d:
            attrs['class'] = d
        else:
            key, val = d.split(':')
            attrs[key] = val

    return field.as_widget(attrs=attrs)

To use it in a Django template, firstly add this widget in the top of the template, similar to the load static widget:
{% load yourapp_template-filters %}
And now you can use it on any form widget as a function, like so:

{% if form.user_name.errors %}
     {{ form.user_name|add_attr:"form-control is-invalid" }}
{% else %}
     {{form.user_name|add_attr:"form-control"}}
{% endif %}

1👍

@ehsan nnnnn‘s answer is great! I tried it, and it works.

I want to clarify and extend it a little bit.

Initialization:

Source: https://docs.djangoproject.com/en/4.0/howto/custom-template-tags/

The app should contain a templatetags directory, at the same level as models.py, views.py, etc. Do not forget to add init.py in the directory! (as stated in the doc)

Attribute declaration:

The code provided by @ehsan nnnnn is helpful if you completely override the attributes section. I have based my code entirely on @ehsan nnnnn‘s solution and extended it to preserve the previous attributes.

NOTE: I am using Python 3.10.1; if you are somehow still using a version before f-string or do not like f-strings, correct it to whatever your heart desires.

Here is my solution:

# templatetags\add_attr.py
from django import template
register = template.Library()


@register.filter(name='add_attr')
def add_attribute(field, css):
    attrs = field.subwidgets[0].data['attrs']  # Accessing the already declared attributes
    definition = css.split(',')

    for d in definition:
        if ':' not in d:
            attrs['class'] += f" {d}"  # Extending the class string
        else:
            key, val = d.split(':')
            attrs[key] += f'{val}'  # Extending the `key` string

    return field.as_widget(attrs=attrs)
{% comment %} HTML template {% endcomment %}
{% if form.username.errors %}
    {{form.username|add_attr:'is-invalid'}}
{% else %}
    {{ form.username }}
{% endif %}

Tested on:

  • Python 3.10.1
  • Django 4.0
  • Bootstrap 5.1

0👍

Try adding a Meta class to your form and assigning the proper model. For instance:

class BasicUserDataForm(forms.Form):
  error_css_class = 'is-invalid'
  user_name = forms.CharField(max_length=20, widget=forms.TextInput(attrs={'placeholder': 'Username', 'class': 'form-control'})) 

  class Meta:
    model = User    
👤Hutch

Leave a comment