request.POST 数据字段未达到表单的 cleaned_data

request.POST data field doesn't get to cleaned_data of form

views.py 中,我有一个名为注册的方法:

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 <QueryDict: {'csrfmiddlewaretoken': ['***'], 'username': ['12312312gdsgdsg'], 'email': ['123123fsdfesgf@gmail.com'], 'password1': ['123fhfhfh'], 'password2': ['989898gdfjgndf']}>

当我调用 form.is_valid() 时,它会清除我的 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')

表格的清理数据打印 returns me 与 post 相同的字典,但没有 password2:

cleaned data {'username': '12312312gdsgdsg', 'email': '123123fsdfesgf@gmail.com', 'password1': '123fhfhfh'}

我是 Django 的新手,我不明白为什么 password2 不能出现在清理过的数据中。关于数据校验的post我已经看过了(Django Forms cleaned_data missing certain fields),但是这个问题的人填错了字段导致他的数据校验不了。我有 2 个相同的密码字段,password1 被清除而 password2 没有。我不明白这个问题。 我的 signup.html 模板:

{% extends 'base.html' %}
{% load static %}
{% block head %}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-F3w7mX95PdgyTmZZMECAngseQB83DfGTowi0iMjiWaeVhAn4FJkqJByhZMI3AhiU" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/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 %}

非常感谢您的帮助!

Django 的 UserCreationForm [Django-doc] 实现了一个 clean_password2 将检查两个密码是否匹配,否则会引发异常。

您可以自定义错误消息:

from django.utils.translation import gettext_lazy as _

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

这里的 'some text to translate' 应该是当两个密码匹配时您要使用的文本。