'How to change the validation error color and position in Django?

I am new to Django. I am trying to make a simple form to match the password. However, when I enter different passwords and press the Save button I get a black validation error above the form. I want to change the error color and position to appear in red color beside or below the control.

Here newuser.html:

{% block content %}
<form method="POST">
{% csrf_token %}
    <table>
        {{frmNewUser.as_table}}
        {% for error in frmNewUser.password.errors %} {% comment %} I tried frmNewUser.non_field_errors too {% endcomment %}
            <p>{{error}}</p>
        {% endfor %}
    </table>
    <input type="submit" name="Save" value="Save" colspan=2>
</form>
{% endblock content %}

Here forms.py:

class NewUserFrom(forms.Form):
    username = forms.CharField(max_length=50, widget=forms.TextInput)
    password = forms.CharField(widget=forms.PasswordInput)
    confirm_password = forms.CharField(label="Confirm password", widget=forms.PasswordInput)
    name = forms.CharField(max_length=50, widget=forms.TextInput)
    email = forms.EmailField(max_length=50, widget=forms.EmailInput)

    def clean(self):
        cleaned_data = super().clean()
        pwd = cleaned_data.get('password')
        cof_pwd = cleaned_data.get('confirm_password')
        if pwd and cof_pwd:
            if pwd != cof_pwd:
                raise forms.ValidationError('Password is not match.')
        return super().clean()

Here views.py:

from django.shortcuts import render
from django.http import HttpResponse, request
from django.db import connection
from django.contrib.auth.decorators import login_required
import pyodbc
from .forms import NewUserFrom

def newUser(request):    
    form = NewUserFrom(request.POST)
         if not form.is_valid():
              context = {'frmNewUser':from}
              return render(request,'login/newuser.html', context)
         return render(request, "login/welcome.html")


Solution 1:[1]

You can change validation error color by doing something like this in your form:


{% block content %}
<form method="POST">
{% csrf_token %}
    <table>
        {{frmNewUser.as_table}}
        {% for error in frmNewUser.password.errors %} {% comment %} I tried frmNewUser.non_field_errors too {% endcomment %}
            <p  style="color: red">{{error}}</p>
        {% endfor %}
    </table>
    <input type="submit" name="Save" value="Save" colspan=2>
</form>
{% endblock content %}

Solution 2:[2]

You are writing out the whole template in html so you can simply add an inline css like so:

<p style="color: red;"> {{ error }} <p>

So when the error message is showed it will render directly in red.

If you are new and you want to add a cool style with a low difficulty bar you should try out bootstrap. They have very simple solutions to add professional-looking validation. Example below:

---- UPDATE #2----

Try this:

{% block content %}
<form method="POST">
    <table>
        {% csrf_token %}

        {# here you print out any form errors #}
        {% if frmNewUser.errors %}
            {% for error in frmNewUser.errors %}
                <p style="color:red">{{ error }}</p>
            {% endfor %}
        {% endif %}
        
        {# here you print out form fields one by one #}
        {# you can render them automatically or write the html manually if you wanna have more control #}
        {% for field in frmNewUser.fields %}
            <tr>
                <td>
                    {{ field }}

                    {# Here you print out any field error #}
                    {% if field.errors %}
                        {% for error in field.errors %}
                            <p style="color: red;"> {{ error }} <p>
                         {% endfor %}
                    {% endif %}

                </td>
            </tr>
        {% endfor %}
     </table>
    <input type="submit" name="Save" value="Save" colspan=2>
</form>
{% endblock content %}

I think they recently updated the docs on this subject because they are surprisingly clear, or maybe i was just a big noob the last time i went over there ;P Anyway, do check them out as i think they can provide additional clarity.

Solution 3:[3]

I faced a similar issue but I used the input's label, and what I did was to change the label to the error and in red color.

For the newuser.html, we can iterate each element in the table. If there is an error, the label will be the error without the html tags. And we can make it red here on html or css. Your call.

{% block content %}
<form method="POST">
{% csrf_token %}
    <table>
        {% for field in frmNewUser %}
            {% if field.errors %}
                <label class="form-label-error" for="{{ field.auto_id }}" style="color:red">
                    {{ field.errors|striptags }}
                </label>
            {% else %}
                <label class="form-label" for="{{ field.auto_id }}">
                    {{ field.label }}
                </label>
            {% endif %}
       {% endfor %}
    </table>
    <input type="submit" name="Save" value="Save" colspan=2>
</form>
{% endblock content %}

However, this will change the label until you submit the form again. It's not very "interactive". For my situation I handled the color change and message (error or ok) with javascript while the user fills the form.

For that, you can add class and onkeypress to the elements in your forms.py so you can later on configurate them.

password = forms.CharField(
                    label='Your Password',
                    required=False,
                    widget=forms.PasswordInput(
                        attrs={
                            'onkeypress': 'password_validation(this)',
                            'class': 'pass_input',
                        }
                    )
                )

Hope it makes sense!

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Godda
Solution 2
Solution 3