Home > Software design >  request.POST data field doesn't get to cleaned_data of form
request.POST data field doesn't get to cleaned_data of form

Time:10-02

In views.py I've got a method called signup:

def signup(request):
    context = {}
    if request.method == 'POST':
        form = SignUpForm(request.POST)
        print("request", request.POST)
        if form.is_valid():
            user = form.save(commit=False) 
            login(request, user)
            return redirect('index')
        else:
            context['form'] = form
    else:  # GET request
        form = SignUpForm()
        context['form'] = form
    return render(request, 'registration/signup.html', context)

Request print gives me all the fields a user entered:

request <QueryDict: {'csrfmiddlewaretoken': ['***'], 'username': ['12312312gdsgdsg'], 'email': ['[email protected]'], 'password1': ['123fhfhfh'], 'password2': ['989898gdfjgndf']}>

When I call form.is_valid() it gets to clean data of my form of forms.py:

class SignUpForm(UserCreationForm):
    username = forms.CharField(
        label="username",
        max_length=30,
        required=True,
        widget=forms.TextInput(
            attrs={
                'type': 'text',
                'placeholder': 'Username',
            }
        ),
    )

    email = forms.EmailField(
        label="email",
        max_length=60,
        required=True,
        widget=forms.TextInput(
            attrs={
                'type': 'text',
                'placeholder': 'Email',
            }
        ),
    )

    password1 = forms.CharField(
        label="password1",
        required=True,
        widget=forms.PasswordInput(
            attrs={
                'type': 'password',
                'placeholder': 'Password',
            }
        ),
    )

    password2 = forms.CharField(
        label="password2",
        required=True,
        widget=forms.PasswordInput(
            attrs={
                'type': 'password',
                'placeholder': 'Confirm Password',
            }
        ),
    )

    def clean(self):
        cleaned_data = super(SignUpForm, self).clean()
        print("cleaned data", cleaned_data)
        password = cleaned_data["password1"]
        confirm_password = cleaned_data["password2"]
        if password != confirm_password:
            self.add_error('confirm_password', "Password and confirm password do not match")
        return cleaned_data

    class Meta:
        model = ServiceUser
        fields = ('username', 'email', 'password1', 'password2')

The form's cleaned data print returns me the same dictionary as the post, but WITHOUT password2:

cleaned data {'username': '12312312gdsgdsg', 'email': '[email protected]', 'password1': '123fhfhfh'}

I'm new to Django and I don't understand why password2 cannot get to be in cleaned data. I have already watched the post about data validation (Django Forms cleaned_data missing certain fields), but the person of this problem made a wrong field and his data couldn't be validated. I've got 2 identical fields for passwords, password1 gets to be cleaned and password2 does not. I cannot understand the problem. My signup.html template:

{% extends 'base.html' %}
{% load static %}
{% block head %}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-F3w7mX95PdgyTmZZMECAngseQB83DfGTowi0iMjiWaeVhAn4FJkqJByhZMI3AhiU" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
<link rel="stylesheet" type="text/css" href="{% static 'css/sign_template.css' %}">
<title>Signup</title>
{% endblock %}
{% block content %}
{% if user.is_authenticated %}
  <meta http-equiv="refresh" content="0; URL={% url 'index' %}" />
{% else %}
<form method="post">
  <div class="sign-card">
    <h3>Signup</h3>
    {% csrf_token %}
    {{ form.errors }}
    {{ form.non_field_errors }}
    <div class="input-div">
      <label for="{{ form.username.id_for_label }}">Username:</label>
      {{ form.username }}
    </div>
    <div class="input-div">
      <label for="{{ form.email.id_for_label }}">Email:</label>
      {{ form.email }}
    </div>
    <div class="input-div">
      <label for="{{ form.password.id_for_label }}">Password:</label>
      {{ form.password1 }}
    </div>
    <div class="input-div">
      <label for="{{ form.password.id_for_label }}">Confirm Password:</label>
      {{ form.password2 }}
    </div>
    {% if form.errors %}
       {% for field in form %}
           {% for error in field.errors %}
              <div class="alert alert-danger alert-dismissible fade show" role="alert">
                  <strong>{{ error|escape }}</strong>
                  <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
              </div>
           {% endfor %}
       {% endfor %}
    {% endif %}

    <button type="submit" class="btn-custom">Sign up</button>
    <p>Already have account? <a href="{% url 'login' %}">Log In</a></p>
  </div>
</form>
{% endif %}
{% endblock %}

Many thanks for your help!

CodePudding user response:

Django's UserCreationForm [Django-doc] implements a clean_password2 that will check if the two passwords match, and raise an exception otherwise.

You can customize the error message with:

from django.utils.translation import gettext_lazy as _

class SignUpForm(UserCreationForm):
    error_messages = {
        'password_mismatch': _('some text to translate')
    }
    # ⋮
    # do not override the clean method

Here the 'some text to translate' should be the text you want to use when the two passwords do not match.

  • Related