You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 08:36:03