如何在Django中正确配置自定义UserCreationForm?
解决自定义UserCreationForm的FieldError问题
报错原因很直接:默认的UserCreationForm自带username字段,但你的MyUser模型没有这个字段(你用email作为USERNAME_FIELD),继承后自然会找不到该字段报错。下面是完整的修正步骤和代码:
第一步:修正MyUser模型与管理器的隐性问题
你的模型和管理器里还有几个不符合Django规范的点,先一起修复:
模型修正点:
- 把
required_fields改为REQUIRED_FIELDS:Django只识别大写的这个常量,用来标记创建用户时除USERNAME_FIELD外的必填字段。 - 删除自定义的
password字段:AbstractBaseUser已经内置了密码相关的字段与加密逻辑,手动添加会导致冲突。 - 调整
REQUIRED_FIELDS内容:移除password,因为密码是通过set_password方法处理的,不需要放在这里。
管理器修正点:
create_staffuser和create_superuser方法调用create_user时参数错误,且缺少必填的fname、lname、phone参数,需调整方法定义与调用逻辑。
修正后的models.py:
from django.db import models from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager from django.contrib.auth.models import PermissionsMixin import uuid class UserManager(BaseUserManager): def create_user(self, fname, lname, email, phone, password=None): if not email: raise ValueError('必须输入邮箱地址') user = self.model( fname=fname, lname=lname, email=self.normalize_email(email), phone=phone, is_superuser=False ) user.set_password(password) user.save(using=self._db) return user # 调整方法参数,接收必填字段 def create_staffuser(self, fname, lname, email, phone, password): user = self.create_user(fname, lname, email, phone, password) user.staff = True user.save(using=self._db) return user # 同样调整参数,确保传入必填字段 def create_superuser(self, fname, lname, email, phone, password): user = self.create_user(fname, lname, email, phone, password) user.staff = True user.admin = True user.is_superuser = True user.save(using=self._db) return user class MyUser(AbstractBaseUser, PermissionsMixin): fname = models.CharField(max_length=100) lname = models.CharField(max_length=100) email = models.EmailField(max_length=200, unique=True) phone = models.CharField(max_length=15) user_id = models.UUIDField(editable=False, primary_key=True, default=uuid.uuid4) is_active = models.BooleanField(default=True) staff = models.BooleanField(default=False) admin = models.BooleanField(default=False) USERNAME_FIELD = 'email' # 修正为大写常量,移除password REQUIRED_FIELDS = ['fname', 'lname', 'phone'] @property def is_staff(self): return self.staff @property def is_admin(self): return self.admin objects = UserManager()
第二步:修正MyUserSignup表单
核心是不要继承UserCreationForm.Meta的默认字段(它包含username),手动指定表单需要的字段:email(作为用户名)、password1、password2(UserCreationForm自带的密码输入与确认字段),再加上自定义的fname、lname、phone。
同时修正clean_email方法的错误,add_error需要明确指定对应的字段名。
修正后的forms.py:
from django import forms from django.contrib.auth.forms import AuthenticationForm, UserCreationForm from django.contrib.auth import get_user_model MyUser = get_user_model() class MyUserLogin(AuthenticationForm): class Meta: model = MyUser fields = ['email', 'password'] class MyUserSignup(UserCreationForm): class Meta: model = MyUser # 手动指定字段,去掉默认的username,替换为email和密码字段 fields = ['email', 'fname', 'lname', 'phone', 'password1', 'password2'] def clean_email(self): email = self.cleaned_data.get('email') if MyUser.objects.filter(email__iexact=email).exists(): # 指定错误对应的字段为email self.add_error('email', '该邮箱已注册账号') return email
验证效果
修改完成后,表单会正确渲染所有自定义字段,不会再出现username字段不存在的错误,同时模型与管理器的逻辑也完全符合Django自定义用户模型的规范,避免后续出现隐性问题。
内容的提问来源于stack exchange,提问作者JalenWithTheHead
相关产品推荐
相关产品推荐

