Django自定义用户模型设置USERNAME_FIELD为username报FieldDoesNotExist错误
问题原因与修复方案
你代码中定义的与模型字段重名的@property装饰器覆盖了原生模型字段,导致Django在生成迁移时无法识别到username、role两个字段的存在,这是报错的核心原因。你之前修改字段名为其他名称即可正常运行,正是因为避开了和@property重名的冲突。
需要修正的问题清单
- 删除与字段重名的
@property方法:你定义的@property def username和@property def role两个属性,名称和模型字段完全一致,直接覆盖了模型字段定义,同时方法内部返回self.username/self.role还会触发无限递归报错,这两个属性完全多余,直接删除即可。 - 修正管理器实例化写法:
objects = UserManager需要改为objects = UserManager(),必须对用户管理器类做实例化才能正常调用。 - 修正必填字段配置:
- 配置项名称是
REQUIRED_FIELDS(复数形式,末尾带s),不是REQUIRED_FIELD REQUIRED_FIELDS列表不允许包含USERNAME_FIELD对应的字段(也就是username),也不需要包含password(密码默认必填),修正为REQUIRED_FIELDS = ['email']即可
- 配置项名称是
- 补充
create_user方法返回值:你写的create_user方法没有返回创建的user对象,会导致创建超级用户等调用场景报错,在方法末尾加return user_object即可。
修复后的完整代码
from django.db import models from django.contrib.auth.models import BaseUserManager, AbstractBaseUser from django.utils.translation import gettext_lazy as _ class UserManager(BaseUserManager): def create_user(self, username, email, password, full_name = None, role='USER'): if not (email and username and password) : raise ValueError ("Missing Data (username, email, password).") user_object = self.model( email=self.normalize_email(email), username=username ) if full_name: user_object.full_name = full_name user_object.set_password(password) user_object.role = role user_object.save(using=self._db) return user_object def create_superuser(self, username, email, password, full_name=None,): user = self.create_user( username= username, email=email, full_name= full_name, password = password, role= 'ADMIN' ) return user def create_staff(self, username, email, password, full_name=None,): user = self.create_user( username= username, email=email, full_name= full_name, password = password, role= 'STAFF' ) return user class User(AbstractBaseUser): class Role(models.TextChoices): User = 'USER', _('User') Admin = 'ADMIN', _('Admin') Staff = 'STAFF', _('Staff') username = models.CharField(max_length=64, unique=True) email = models.EmailField(max_length=128, unique= True, verbose_name="Email") full_name = models.CharField(max_length=128, verbose_name="Full Name", null=True, blank=True) active = models.BooleanField(default=True, verbose_name="Active") role = models.CharField(max_length=10, choices=Role.choices, default=Role.User, verbose_name="Role") created_at = models.DateTimeField(auto_now_add=True) modified_at = models.DateTimeField(auto_now=True) objects = UserManager() USERNAME_FIELD = 'username' REQUIRED_FIELDS = ['email'] def __str__(self): return self.username @property def is_admin(self): return (self.role == self.Role.Admin) @property def is_staff(self): return (self.role == self.Role.Staff) @property def is_active(self): return self.active
修改完成后删除已生成的历史迁移文件,重新执行makemigrations和migrate命令即可正常生成字段。
内容的提问来源于stack exchange,提问作者Ben Dover
相关产品推荐
相关产品推荐

