自定义User模型使用Django密码重置遇FieldError及admin登录问题
我来帮你梳理下问题的来龙去脉和具体修复步骤:
首先说第一个密码重置时的FieldError:
Django内置的密码重置视图(PasswordResetView)在查询要发送重置邮件的用户时,默认会过滤is_active=True的用户。而你最初的自定义User模型里,活跃状态字段叫active,不是Django预期的is_active,所以才会抛出无法解析该字段的错误。
你把字段改成is_active后解决了密码重置的问题,但超级用户登不上Admin,这是因为你的UserManager没有同步更新字段赋值逻辑——原来的管理器还是在给旧的字段名赋值,导致新模型的is_staff和is_admin字段没有被正确设置。
具体修复步骤:
同步更新UserManager的字段赋值
原来的UserManager里,创建用户时是给user.active = is_active、user.staff = is_staff这些旧字段赋值,但修改后的User模型字段已经改成is_active、is_staff、is_admin了,必须把这些赋值语句同步修改:class UserManager(BaseUserManager): def create_user(self, email, password=None, is_staff=False, is_admin=False, is_active=True): if not email: raise ValueError('Users must have an email address.') if not password: raise ValueError('Users must have a password.') user = self.model( email = self.normalize_email(email) ) # 改成和User模型字段一致的名称 user.is_staff = is_staff user.is_admin = is_admin user.is_active = is_active user.set_password(password) user.save(using=self._db) return user def create_staffuser(self, email, password=None): user = self.create_user( email, password=password, is_staff=True ) return user def create_superuser(self, email, password=None): user = self.create_user( email, password=password, is_staff=True, is_admin=True # is_active默认是True,不需要额外传,除非你有特殊需求 ) return user确认Admin权限方法的逻辑
修改后的User模型去掉了is_staff、is_admin的@property装饰器,这没问题,因为现在字段本身就是is_staff和is_admin了。不过要确保has_perm和has_module_perms方法的逻辑符合Admin要求:has_perm:当前返回True的逻辑适合超级用户,确保他们拥有所有权限;如果是普通用户,你可以后续根据需求调整权限逻辑。has_module_perms:返回True表示允许访问所有应用的Admin界面,这也是超级用户需要的权限。
重新创建超级用户(推荐)
如果你是在修改模型前创建的超级用户,数据库里的旧超级用户可能is_staff或is_admin字段没有被正确设置(因为之前是通过@property从旧字段获取的)。所以最好删除原来的超级用户,重新创建:python manage.py createsuperuser
额外小提示:
- Django的自定义User模型尽量遵循官方推荐的字段名称(比如
is_active、is_staff、is_superuser),这样可以直接复用Django内置的视图、表单和Admin逻辑,减少自定义适配的工作量。 - 如果你实在不想改字段名称,也可以自定义
PasswordResetView,重写get_users方法来过滤active=True的用户,但显然用标准字段更省心。
内容的提问来源于stack exchange,提问作者annmarie-switzer

