Django自定义用户模型(BaseUserManager/AbstractBaseUser)普通用户登录失败
问题诊断与修复方案
我仔细排查了你的自定义User模型代码,发现几个核心问题导致普通用户无法登录,下面逐个拆解并给出修复后的完整代码:
1. UserManager中的无限递归调用
在MyUserManager.create_user方法里,你不小心写了一行递归调用代码:
user = self.create_user(email, password=password, name= name, )
这会导致调用create_user时陷入无限循环,不仅无法正确初始化用户对象,还会覆盖后续的密码设置逻辑,直接导致用户密码无法正常加密存储,这是普通用户登录失败的关键原因,必须删掉这行。
2. 模型类中错误定义了create_user方法
create_user是用户管理器(UserManager)的专属职责,你的MyUser模型类完全不需要重复定义这个方法——这会干扰管理器的正常工作流程,直接删掉模型里的create_user方法即可。
3. 缺少is_superuser字段
AbstractBaseUser并不自带is_superuser字段,你在管理器里设置了user.is_superuser = False,但模型里没有声明这个字段,会导致用户对象缺失关键属性,可能引发权限验证环节的隐性错误,需要在MyUser模型中显式添加该字段。
4. Python3兼容问题:__unicode__改为__str__
如果你的项目基于Python3运行,建议把__unicode__替换为__str__(虽然不直接影响登录,但能避免某些场景下的字符串显示异常)。
修复后的完整代码
models.py
from django.contrib.auth.base_user import BaseUserManager, AbstractBaseUser from django.db import models class MyUserManager(BaseUserManager): def create_user(self, email, name="anonymous", password=None): if not email: raise ValueError('请输入邮箱地址') # 初始化用户对象 user = self.model( email=MyUserManager.normalize_email(email), name=name, ) # 加密并设置密码 user.set_password(password) # 普通用户默认权限配置 user.is_superuser = False user.is_admin = False user.save(using=self._db) return user def create_superuser(self, email, password): # 复用create_user创建基础用户 user = self.create_user(email, password=password) # 配置超级用户权限 user.is_admin = True user.is_superuser = True user.save(using=self._db) return user class MyUser(AbstractBaseUser): email = models.EmailField(max_length=254, unique=True, db_index=True, null=False, blank=False) name = models.CharField(max_length=50, null=True, blank=True) is_active = models.BooleanField(default=True) is_admin = models.BooleanField(default=False) # 添加缺失的超级用户标识字段 is_superuser = models.BooleanField(default=False) objects = MyUserManager() USERNAME_FIELD = 'email' REQUIRED_FIELDS = [] def get_full_name(self): return self.name # 适配Python3的字符串显示方法 def __str__(self): return self.email def has_perm(self, perm, obj=None): # 可根据实际业务调整权限逻辑,当前默认返回True表示拥有所有权限 return True def has_module_perms(self, app_label): # 同理,可按需调整模块权限逻辑 return True @property def is_staff(self): # 管理员自动拥有后台访问权限,符合Django默认逻辑 return self.is_admin
额外注意事项
- 修复代码后,必须执行数据库迁移来同步字段变更:
python manage.py makemigrations python manage.py migrate - 之前创建的普通用户可能因密码逻辑错误无法登录,建议删除后重新创建测试;
- 确保登录视图使用Django官方的
authenticate方法验证用户,示例代码:from django.contrib.auth import authenticate, login from django.shortcuts import redirect, render from django.contrib import messages def user_login(request): if request.method == 'POST': email = request.POST.get('email') password = request.POST.get('password') user = authenticate(request, email=email, password=password) if user: login(request, user) return redirect('home') else: messages.error(request, '邮箱或密码错误') return render(request, 'login.html')
内容的提问来源于stack exchange,提问作者maryam
相关产品推荐
相关产品推荐

