在Django中如何不使用username字段创建自定义用户模型
Django 无username字段自定义用户模型实现方案
AbstractBaseUser本身并未强制要求定义username字段,仅要求指定一个唯一字段作为USERNAME_FIELD(用户身份校验的唯一标识),将该字段设置为你需要的业务字段(如邮箱、手机号)即可完全去除username字段。
1. 编写自定义用户模型及管理器
首先继承AbstractBaseUser和PermissionsMixin(后者用于支持Django原生权限体系),同时自定义用户管理器适配无username的逻辑,代码示例如下:
from django.db import models from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin from django.contrib.auth.base_user import BaseUserManager # 自定义用户管理器 class CustomUserManager(BaseUserManager): def create_user(self, email, password, **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() return user def create_superuser(self, email, password, **extra_fields): extra_fields.setdefault('is_staff', True) extra_fields.setdefault('is_superuser', True) extra_fields.setdefault('is_active', True) if extra_fields.get('is_staff') is not True: raise ValueError("超级用户必须设置is_staff=True") if extra_fields.get('is_superuser') is not True: raise ValueError("超级用户必须设置is_superuser=True") return self.create_user(email, password, **extra_fields) # 自定义用户模型,全程不定义username字段 class CustomUser(AbstractBaseUser, PermissionsMixin): email = models.EmailField(unique=True, verbose_name="邮箱") full_name = models.CharField(max_length=50, verbose_name="姓名") phone = models.CharField(max_length=11, blank=True, verbose_name="手机号") is_staff = models.BooleanField(default=False, verbose_name="是否可进入后台") is_active = models.BooleanField(default=True, verbose_name="是否启用") created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间") # 指定邮箱作为身份标识字段,替代默认的username USERNAME_FIELD = 'email' # 指定创建用户时额外必填的字段,无需包含USERNAME_FIELD和password REQUIRED_FIELDS = ['full_name'] # 绑定自定义管理器 objects = CustomUserManager() def __str__(self): return f"{self.full_name} <{self.email}>"
2. 项目配置
在settings.py中添加如下配置,指定全局用户模型为你自定义的类:
# 替换规则为:你的应用名.自定义用户类名,示例中应用名为users,模型类名为CustomUser AUTH_USER_MODEL = 'users.CustomUser'
注意:该配置必须在项目首次执行python manage.py migrate前完成,否则已生成的默认用户表会和自定义表产生冲突。如果是已完成初始迁移的项目,需要先清空数据库、删除所有应用中migrations目录下除__init__.py外的所有文件,再重新生成迁移文件执行迁移。
3. 配套适配注意事项
- 后续业务代码中关联用户外键时,优先使用
from django.conf import settings后引用settings.AUTH_USER_MODEL作为外键关联对象,不要直接导入自定义用户类,避免出现循环依赖问题。 - 如果使用Django自带的Admin后台,需要重写
UserAdmin类适配你自定义的字段,否则后台会因为找不到username字段报错,示例适配代码如下:
# 在对应应用的admin.py中添加 from django.contrib import admin from django.contrib.auth.admin import UserAdmin from .models import CustomUser class CustomUserAdmin(UserAdmin): # 重写字段集,移除所有username相关配置 fieldsets = ( (None, {'fields': ('email', 'password')}), ('个人信息', {'fields': ('full_name', 'phone')}), ('权限', {'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions')}), ('时间信息', {'fields': ('created_at', 'last_login')}), ) add_fieldsets = ( (None, { 'classes': ('wide',), 'fields': ('email', 'full_name', 'password1', 'password2'), }), ) list_display = ('email', 'full_name', 'is_staff', 'is_active') search_fields = ('email', 'full_name') ordering = ('email',) admin.site.register(CustomUser, CustomUserAdmin)
内容的提问来源于stack exchange,提问作者Ghassen Jemaï
相关产品推荐
相关产品推荐

