Django3.2扩展自定义UserModel后Admin创建的用户无法登录如何解决
问题核心原因
你遇到的Admin面板创建用户无法登录问题,和自定义用户模型继承AbstractUser的实现思路无关,故障点出在Admin注册逻辑上:
- 你直接调用
admin.site.register(UserModel)注册模型时,Django会使用通用的ModelAdmin类处理表单提交,这个通用类没有内置用户密码哈希逻辑,会把你在创建表单里输入的明文密码直接存入数据库 - 用户登录时Django会自动对输入的明文密码做哈希,再和数据库里存的值做比对,此时数据库里存的是未哈希的明文,校验必然失败,所以即使勾选了staff权限也无法登录
现有代码的两处待修正点
- Settings配置名错误:Django指定自定义用户模型的配置项是
AUTH_USER_MODEL,不是USER_MODEL,配置值格式为你的应用名.UserModel,如果配置写错,后续模型关联用户外键时会出现找不到模型的错误 - 自定义
type字段缺少默认值:你在UserModel里新增的type字段没有设置默认值、也没允许为空,执行数据库迁移、创建未指定type值的用户时会抛出字段非空错误,建议修改为:
type = models.CharField(choices=UserType.choices, max_length=1, default=UserType.CUSTOMER)
你重写的first_name、last_name字段调整max_length为120不影响原有逻辑,不需要额外修改。
具体修复方案
不要直接用通用ModelAdmin注册用户模型,改用Django内置的UserAdmin类——这个类已经封装好了密码两次输入校验、自动哈希存储、权限字段处理的全套用户管理逻辑,你只需要把新增的自定义字段注册到对应的表单配置里即可。
修改admin.py代码为如下内容:
from django.contrib import admin from django.contrib.auth.admin import UserAdmin as BaseUserAdmin from .models import UserModel class CustomUserAdmin(BaseUserAdmin): # 用户列表页展示字段,新增type字段 list_display = ('username', 'email', 'first_name', 'last_name', 'type', 'is_staff', 'is_superuser') # 用户编辑页的字段分组,在原有默认分组后追加自定义的type字段 fieldsets = BaseUserAdmin.fieldsets + ( ('用户类型', {'fields': ('type',)}), ) # 新建用户时的表单字段,保留原有密码1、密码2的校验项,追加你的自定义字段 add_fieldsets = ( (None, { 'classes': ('wide',), 'fields': ('username', 'password1', 'password2', 'first_name', 'last_name', 'email', 'type', 'is_staff', 'is_superuser'), }), ) admin.site.register(UserModel, CustomUserAdmin)
代码修改完成后,删除之前在Admin面板中创建的、密码存储为明文的无效用户条目,重新通过Admin面板创建用户即可正常登录,此时查看用户的password字段,会自动存储为pbkdf2_sha256$开头的标准哈希值。
注意:不要自行在
UserModel的save方法中添加密码哈希逻辑,BaseUserAdmin已经完整处理了所有密码相关的流程,重复哈希会导致密码校验失效。
内容的提问来源于stack exchange,提问作者John Jethro Rashbold
相关产品推荐
相关产品推荐

