Django注册提交报错:create_user()参数不符且表单验证失效
Hey there! Let's work through the two issues you're facing with your Django registration form—first the argument mismatch error, then adding the missing validation logic.
Fixing the create_user() Argument Error
That error pops up because Django's User.objects.create_user() method only accepts up to 4 positional arguments (username, optional email, optional password, plus keyword-only extra fields). If you're passing extra fields as positional arguments in your view (like first_name or last_name directly after the required ones), it'll throw that "too many arguments" error.
Here's the correct way to call it—use keyword arguments for all fields, including extra ones:
# In your view where you handle form submission if form.is_valid(): cleaned_data = form.cleaned_data # Create user with keyword arguments to avoid positional argument issues user = User.objects.create_user( username=cleaned_data['username'], email=cleaned_data.get('email', ''), # Use get() to handle optional fields password=cleaned_data['password1'], # Add any extra fields here as keywords first_name=cleaned_data.get('first_name', ''), last_name=cleaned_data.get('last_name', '') ) # Rest of your logic (login, redirect, etc.)
Alternatively, if you have multiple extra fields, you can unpack them with **kwargs to keep it clean:
cleaned_data = form.cleaned_data # Extract required fields user_core_data = { 'username': cleaned_data['username'], 'email': cleaned_data.get('email', ''), 'password': cleaned_data['password1'] } # Grab extra fields excluding form-specific ones (like password2) extra_fields = {k: v for k, v in cleaned_data.items() if k not in ['username', 'email', 'password1', 'password2']} # Combine and create user user = User.objects.create_user(**user_core_data, **extra_fields)
Adding Missing Form Validation Logic
Next, let's beef up your forms.py with the validation rules you're missing—password match check, unique username/email checks. We'll extend UserCreationForm and add custom clean methods:
from django import forms from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.models import User from django.core.exceptions import ValidationError class CustomRegistrationForm(UserCreationForm): # Make email required (adjust if you want it optional) email = forms.EmailField( required=True, help_text="Required. Enter a valid email address that isn't already registered." ) class Meta: model = User fields = ['username', 'email', 'password1', 'password2'] # Validate password match def clean_password2(self): password1 = self.cleaned_data.get("password1") password2 = self.cleaned_data.get("password2") if password1 and password2 and password1 != password2: raise ValidationError("Passwords do not match. Please try again.") return password2 # Check if username is already taken def clean_username(self): username = self.cleaned_data.get("username") if User.objects.filter(username=username).exists(): raise ValidationError("This username is already in use. Choose a different one.") return username # Check if email is already registered def clean_email(self): email = self.cleaned_data.get("email") if User.objects.filter(email=email).exists(): raise ValidationError("This email is already linked to an account. Log in or use a different email.") return email
Don't Forget to Update Your Template
Make sure your template displays the validation errors so users know what went wrong. Add error messages next to each field:
<!-- Example template snippet --> <form method="post"> {% csrf_token %} <div> {{ form.username.label_tag }} {{ form.username }} {{ form.username.errors }} </div> <div> {{ form.email.label_tag }} {{ form.email }} {{ form.email.errors }} </div> <div> {{ form.password1.label_tag }} {{ form.password1 }} {{ form.password1.errors }} </div> <div> {{ form.password2.label_tag }} {{ form.password2 }} {{ form.password2.errors }} </div> <button type="submit">Register</button> {{ form.non_field_errors }} </form>
Finally, update your view to use CustomRegistrationForm instead of the default UserCreationForm, and you're good to go—validation will run automatically when form.is_valid() is called.
内容的提问来源于stack exchange,提问作者M.Sameh

