Skip to main content
Source Link

Django - Register User with Confirm Password validation/error message on Bootstrap form

I am trying to create a Register User form using Django 6 and Bootstrap 5. The form displays field level validation/error messages. However, I am not sure how to include the Confirm Password field (with error/validation messages), since this field is not a part of the model but is needed to ensure Password is correct before saving the form. Below is the source. Is there any other method/approach of achieving the same output (i.e. field level error/validation messages on the html form) in a better and more efficient way? Thanks to the code by Francisco Alejandro Rojas

models.py

class UserMaster(models.Model):
    username = models.CharField(max_length=50, unique=True)
    password = models.CharField(max_length=15)
    
    def __str__(self):
        return self.username

forms.py

class UserMasterForm(forms.ModelForm):
    class Meta:
       model = UserMaster
       fields = ['username', 'password']
       widgets = {
            'username': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Enter User Name'}),
            'password': forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': 'Enter Password'}),
            'password2': forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': 'Confirm Password'}),
          }
       error_messages = {
            'username': {
                'required': ('Username cannot be empty'),
                'unique': ('Username already taken')},
            'password': {
                'required': ('Password cannot be empty')},
          'password2': {
             'required': ('Confirmation password cannot be empty')},
        }

    def __init__(self, *args, **kwargs):
       super(UserMasterForm, self).__init__(*args, **kwargs)
       for field in iter(self.fields):
          self.fields[field].widget.attrs.update({'class': 'form-control', })

views.py

def register_view(request):
    if request.method == 'POST':
        form = UserMasterForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('login')
        else:
            change_class_for_error(form)
            return render(request, 'mainapp/register.html', {'form': form})
    else:
        form = UserMasterForm()
        return render(request, 'mainapp/register.html', {'form': form})

def change_class_for_error(myform):
    for field in myform:
        if field.errors:
            myform.fields[field.name].widget.attrs['class'] = 'form-control is-invalid'

signup.html

<form action="" class="g-3 mx-2" method="POST" novalidate>
{% csrf_token %}
<div class="row">
    <div class="col-md-5">
        <label class="form-label">Username</label>
        {{ form.username }}
        {% for error in form.username.errors  %}
            <div class="invalid-feedback">{{ error }}
        {% endfor %}
    </div>
</div>
<div class="row">
    <div class="col-md-6">
        <label class="form-label">Password</label>
        {{ form.password }}
        {% for error in form.password.errors  %}
            <div class="invalid-feedback">{{ error }}
        {% endfor %}
    </div>
    <div class="col-md-6">
        <label class="form-label">Confirm Password</label>
        <input class="form-control {% if form.errors %} is-invalid {% endif %}"
               name="password2" type="text" >
        {% for error in form.password2.errors  %}
            <div class="invalid-feedback">{{ error }}
        {% endfor %}
    </div>
    <div class="flex gap-3 mt-3 mb-2">
        <button class="btn btn-primary button-label rounded-0 w-25" type="submit">
            <a class="text-decoration-none" href="">Save</a>
        </button>
        <button class="btn btn-warning button-label rounded-0 w-25" type="button">
            <a class="text-decoration-none" href="#">Cancel</a>
        </button>
    </div>
</div>
</form>