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

项目中期从AbstractUser切换到AbstractBaseUser移除username字段遇阻求助

Django自定义用户模型问题解决

问题背景

  • 用AbstractUser扩展用户模型,设置以email作为认证字段,但AbstractUser仍强制依赖username字段
  • 模型里设username=None,执行makemigrations时报错:CustomUser指定了未知字段'username'
  • 换成继承AbstractBaseUser后,执行迁移还是报同样的错误
  • 删掉username=None能通过迁移,但创建用户时is_valid()校验失败,表单提示username必填且不能为null

代码文件

models.py

# 请粘贴你的models代码到这里

forms.py

# 请粘贴你的forms代码到这里

admin.py

# 请粘贴你的admin代码到这里

解决方案

1. 处理username字段依赖问题

方案一:继续使用AbstractUser

不需要设置username=None,直接重写username字段并配置认证参数即可:

from django.contrib.auth.models import AbstractUser
from django.db import models

class CustomUser(AbstractUser):
    email = models.EmailField(unique=True)
    # 将username设为可选字段
    username = models.CharField(max_length=150, blank=True, null=True)
    # 指定email作为用户认证的唯一字段
    USERNAME_FIELD = 'email'
    # 移除username,只保留必要的必填字段
    REQUIRED_FIELDS = []

同时修改用户创建表单,排除username字段:

from django.contrib.auth.forms import UserCreationForm
from .models import CustomUser

class CustomUserCreationForm(UserCreationForm):
    class Meta:
        model = CustomUser
        fields = ('email', 'password1', 'password2')

方案二:切换到AbstractBaseUser

完全自定义用户模型,不需要处理username字段,但必须实现必要的用户管理器和基础方法:

from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
from django.db import models

# 自定义用户管理器,处理用户创建逻辑
class CustomUserManager(BaseUserManager):
    def create_user(self, email, password=None, **extra_fields):
        if not email:
            raise ValueError('必须填写邮箱地址')
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, password=None, **extra_fields):
        extra_fields['is_staff'] = True
        extra_fields['is_superuser'] = True
        return self.create_user(email, password, **extra_fields)

# 自定义用户模型
class CustomUser(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(unique=True)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = CustomUserManager()

    def get_full_name(self):
        return self.email

    def get_short_name(self):
        return self.email

2. 切换继承类的迁移注意事项

从AbstractUser切换到AbstractBaseUser必须清理旧迁移和相关数据,步骤如下:

  • 删除项目所有migrations目录下的迁移文件(保留__init__.py)
  • 清空数据库中的CustomUser表,同时删除django_migrations表中与该模型相关的迁移记录
  • 重新执行迁移命令:
python manage.py makemigrations
python manage.py migrate

注意:生产环境操作前必须备份数据,或编写数据迁移脚本将旧用户数据导入新模型

内容的提问来源于stack exchange,提问作者Topher76

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 09:42:43