Django 2.0表单验证问题:ValidationError返回password_mismatch及邮箱验证需求
Hey there! Let's work through your Django 2.0 form issues step by step—they're totally fixable.
It sounds like your custom ValidationError is getting overshadowed by the built-in logic from UserCreationForm. Here are the most likely causes and fixes:
- You’re missing password fields in your form:
UserCreationFormrequirespassword1andpassword2for its password-matching validation. If yourMeta.fieldsdon’t include these, the form will throw apassword_mismatcherror by default (even if your custom validation is correct). Add them to yourfieldslist like this:class Meta: model = User fields = ('first_name', 'last_name', 'email', 'code', 'password1', 'password2') - Your
clean()method isn’t returningcleaned_data: When you overrideclean(), you must return the cleaned data at the end. If you skip this, the parent class’s validation (including password checks) can behave unpredictably. Make sure yourclean()method ends withreturn cleaned_data. - Template isn’t rendering password fields: Double-check your template includes form fields for
password1andpassword2—if they’re missing, the form will receive no password data, triggering thepassword_mismatcherror before your custom validation runs.
Your current email validation has a small but critical issue: if the email field fails earlier validation (like an invalid format), cleaned_data['email'] will throw a KeyError. Let’s fix that, plus add the post-email-exists behavior you want.
Updated forms.py Code
from django.contrib.auth import forms as auth_forms from django.utils.translation import gettext_lazy as _ from .models import User class RegisterForm(auth_forms.UserCreationForm): code = forms.CharField(label=_('valid code'), max_length=6) def clean(self): cleaned_data = super().clean() # Use .get() to safely retrieve email (avoids KeyError if email is invalid) email = cleaned_data.get('email') if email: # Case-insensitive check to catch duplicates like "Email@Example.com" if User.objects.filter(email__iexact=email).exists(): raise forms.ValidationError( _('This email is already registered. Please log in or use a different email.'), code='email_already_in_use' ) # Always return cleaned_data! return cleaned_data class Meta: model = User fields = ('first_name', 'last_name', 'email', 'code', 'password1', 'password2')
Adding Post-Validation Logic (When Email Exists)
In your view, you can detect the email_already_in_use error and add custom behavior—like prompting the user to log in or reset their password:
from django.shortcuts import render, redirect from django.contrib import messages from .forms import RegisterForm def register(request): if request.method == 'POST': form = RegisterForm(request.POST) if form.is_valid(): # Process valid registration (e.g., save user, send verification email) user = form.save(commit=False) # Add any extra steps here (like activating the user, saving the verification code) user.save() messages.success(request, _('Registration successful! Please log in.')) return redirect('login') else: # Check if the email exists error is present all_errors = form.errors.get('__all__', []) if any(error.code == 'email_already_in_use' for error in all_errors): messages.info(request, _('That email is already in use. Click here to reset your password or log in.')) else: form = RegisterForm() return render(request, 'registration/register.html', {'form': form})
This way, when a user tries to register with an existing email, they’ll get a helpful prompt pointing them to login or password reset options.
内容的提问来源于stack exchange,提问作者nataila

