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

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

额外注意事项

  1. 修复代码后,必须执行数据库迁移来同步字段变更:
    python manage.py makemigrations
    python manage.py migrate
    
  2. 之前创建的普通用户可能因密码逻辑错误无法登录,建议删除后重新创建测试;
  3. 确保登录视图使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 09:05:20