Django自定义用户模型注册表单失效及create_user提示异常求助
Django自定义注册表单无法创建用户问题排查
问题现象
- 通过
manage.py shell可正常创建用户,但点击注册表单提交按钮后页面仅刷新,无用户创建操作 - VS Code中
Account.objects.create_user代码行标红,提示Cannot access attribute "create_user" for class "BaseManager[Account]"
相关代码
forms.py
from django import forms from .models import Account class RegistrationForm(forms.ModelForm): password = forms.CharField(widget=forms.PasswordInput(attrs={ 'placeholder': 'Enter Password', })) confirm_password = forms.CharField(widget=forms.PasswordInput(attrs={ 'placeholder': 'Confirm Password', })) email = forms.EmailField( max_length=255, help_text="Required. Add a valid email address.") document = forms.CharField(widget=forms.TextInput(attrs={ 'placeholder': '(CPF/RG/PASSPORT)', }), max_length=15, help_text="Enter a valid CPF, RG, or Passport.") address = forms.CharField(widget=forms.TextInput(attrs={ 'placeholder': '1337 Example St, FL, US', }), max_length=255, help_text="Enter your address.") class Meta: model = Account fields = ['first_name', 'last_name', 'username', 'phone_number', 'email', 'address', 'document', 'password'] def __init__(self, *args, **kwargs): super(RegistrationForm, self).__init__(*args, **kwargs) self.fields['phone_number'].widget.attrs['placeholder'] = '(xx) x xxxx-xxxx' for field in self.fields: self.fields[field].widget.attrs['class'] = 'form-control'
models.py
from django.db import models from django.contrib.auth.models import AbstractBaseUser, BaseUserManager class MyAccountManager(BaseUserManager): def create_user(self, first_name, last_name, document, phone_number, email, username, address=None, password=None, TCM_wallet=0): if not email: raise ValueError('User must have an email address.') if not username: raise ValueError('User must have a username.') if not document: raise ValueError('User must provide the document.') if not address: raise ValueError('User must provide the address.') user = self.model( email=self.normalize_email(email), username=username, first_name=first_name, last_name=last_name, phone_number=phone_number, document=document, address=address, TCM_wallet=TCM_wallet, ) user.set_password(password) user.save(using=self._db) return user def create_superuser(self, first_name, last_name, username, phone_number, document, email, password, address, TCM_wallet=0): user = self.create_user( email=self.normalize_email(email), username=username, first_name=first_name, last_name=last_name, document=document, phone_number=phone_number, address=address, password=password, TCM_wallet=TCM_wallet, ) user.is_admin = True user.is_active = True user.is_staff = True user.is_superadmin = True user.save(using=self._db) return user class Account(AbstractBaseUser): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) username = models.CharField(max_length=50, unique=True) email = models.EmailField(max_length=100, unique=True) phone_number = models.CharField(max_length=50, blank=True) document = models.CharField( max_length=15, unique=True, help_text='Required. Enter a valid document (CPF, RG, or Passport).') address = models.CharField(max_length=100, blank=True, null=True) TCM_wallet = models.FloatField(default=0, editable=True) # required fields date_joined = models.DateTimeField(auto_now_add=True) last_login = models.DateTimeField(auto_now=True) is_admin = models.BooleanField(default=False) is_staff = models.BooleanField(default=False) is_active = models.BooleanField(default=True) is_superadmin = models.BooleanField(default=False) USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['username', 'first_name', 'last_name', 'document', 'address', 'phone_number',] objects = MyAccountManager() def __str__(self): return self.email def has_perm(self, perm, obj=None): return self.is_admin def has_module_perms(self, app_label): return True
views.py
from django.shortcuts import render, redirect from .forms import RegistrationForm from .models import Account def register(request): if request.method == 'POST': form = RegistrationForm(request.POST) if form.is_valid(): first_name = form.cleaned_data['first_name'] last_name = form.cleaned_data['last_name'] email = form.cleaned_data['email'] phone_number = form.cleaned_data['phone_number'] document = form.cleaned_data['document'] address = form.cleaned_data['address'] password = form.cleaned_data['password'] username = email.split('@')[0] user = Account.objects.create_user( first_name=first_name, last_name=last_name, email=email, document=document, address=address, password=password, username=username, ) user.phone_number = phone_number user.save() else: form = RegistrationForm() context = { 'form': form, } return render(request, 'accounts/register.html', context) def login(request): return render(request, 'accounts/login.html') def logout(request): # assuming 'login' is the name of your login url pattern return redirect('login')
问题排查与修复
1. 表单验证失败导致无操作
表单中添加了confirm_password字段,但未添加密码匹配验证逻辑,提交时会因密码不匹配直接验证失败,后续代码无法执行。需在RegistrationForm中添加密码验证的clean方法:
def clean(self): cleaned_data = super(RegistrationForm, self).clean() password = cleaned_data.get('password') confirm_password = cleaned_data.get('confirm_password') if password != confirm_password: raise forms.ValidationError("Passwords do not match!") return cleaned_data
同时,Meta.fields中无需包含username(view中通过email生成该值),需移除该字段避免渲染多余输入框:
class Meta: model = Account fields = ['first_name', 'last_name', 'phone_number', 'email', 'address', 'document', 'password']
2. create_user参数缺失
MyAccountManager.create_user方法要求传入phone_number参数,但view中调用时未传递,导致调用失败。需在view的create_user调用中补充该参数:
user = Account.objects.create_user( first_name=first_name, last_name=last_name, email=email, document=document, address=address, password=password, username=username, phone_number=phone_number )
无需后续单独设置user.phone_number并二次保存。
3. VS Code类型提示错误
这是Django类型推断问题,可给MyAccountManager添加类型注解解决:
from typing import TypeVar UserType = TypeVar('UserType', bound='Account') class MyAccountManager(BaseUserManager[UserType]): def create_user(self, first_name: str, last_name: str, document: str, phone_number: str, email: str, username: str, address: str | None = None, password: str | None = None, TCM_wallet: float = 0) -> UserType: # 原方法内容不变
4. 表单提交后无反馈
用户注册成功后需添加重定向操作,避免停留在原页面,可在用户创建完成后添加:
return redirect('login')
内容的提问来源于stack exchange,提问作者Clovis Aquino Borges
相关产品推荐
相关产品推荐

