自定义用户模型及管理器后创建超级用户报错与类型不兼容问题
自定义用户模型及管理器后创建超级用户报错与类型不兼容问题
嘿,看你遇到的这两个问题,我太熟悉了——自定义Django用户模型的时候很容易踩这些坑!我来帮你一步步搞定它们:
第一个问题:创建超级用户时报错 TypeError: UserManager.create_superuser() missing 1 required positional argument: 'username'
这个报错的核心原因是:你只重写了管理器的create_user方法,但默认的create_superuser还是依赖username字段,而你的自定义用户模型应该是用email替代了username作为唯一标识对吧?
解决办法很简单,必须在你的CustomUserManager里重写create_superuser方法,让它不再依赖username,而是用email来创建超级用户。补全后的管理器代码应该是这样的:
from django.contrib.auth.base_user import BaseUserManager class CustomUserManager(BaseUserManager): def create_user(self, email, password=None, **extra_fields): if not email: raise ValueError('The Email field must be set') email = self.normalize_email(email) user = self.model(email=email, **extra_fields) user.set_password(password) user.save(using=self._db) # 别忘了这行,把用户保存到数据库 return user def create_superuser(self, email, password=None, **extra_fields): # 自动设置超级用户的权限字段 extra_fields.setdefault('is_staff', True) extra_fields.setdefault('is_superuser', True) # 做个校验,确保权限字段没被错误覆盖 if extra_fields.get('is_staff') is not True: raise ValueError('Superuser must have is_staff=True.') if extra_fields.get('is_superuser') is not True: raise ValueError('Superuser must have is_superuser=True.') # 调用我们重写的create_user来创建超级用户 return self.create_user(email, password, **extra_fields)
另外还要确保你的CustomUser模型里设置了:
USERNAME_FIELD = 'email' # 指定用email作为登录标识 REQUIRED_FIELDS = [] # 因为email已经是必填的,这里不需要额外字段
这样再运行createsuperuser命令时,就会提示你输入email而不是username,不会再报错啦。
第二个问题:类型检查提示 CustomUserManager 与 UserManager[Self@AbstractUser] 不兼容
这个是类型检查工具(比如mypy)的提示,原因是你的管理器没有正确声明泛型类型,和自定义用户模型的类型不匹配。
解决办法是给CustomUserManager加上泛型注解,让它明确知道自己管理的是CustomUser类型:
首先,在管理器文件里导入必要的类型工具,然后修改管理器的继承:
from django.contrib.auth.base_user import BaseUserManager from typing import TypeVar, Type from .models import CustomUser # 导入你的自定义用户模型 # 定义一个类型变量,绑定到CustomUser UserType = TypeVar('UserType', bound=CustomUser) class CustomUserManager(BaseUserManager[UserType]): def create_user(self, email: str, password: str | None = None, **extra_fields) -> UserType: # 这里保留你之前的create_user逻辑,返回类型指定为UserType if not email: raise ValueError('The Email field must be set') email = self.normalize_email(email) user = self.model(email=email, **extra_fields) user.set_password(password) user.save(using=self._db) return user def create_superuser(self, email: str, password: str | None = None, **extra_fields) -> UserType: # 同样保留逻辑,返回类型指定为UserType extra_fields.setdefault('is_staff', True) extra_fields.setdefault('is_superuser', True) if extra_fields.get('is_staff') is not True: raise ValueError('Superuser must have is_staff=True.') if extra_fields.get('is_superuser') is not True: raise ValueError('Superuser must have is_superuser=True.') return self.create_user(email, password, **extra_fields)
这样类型检查工具就能识别出CustomUserManager是专门管理CustomUser的,就不会再提示类型不兼容的问题了。
最后再提醒一下:修改完模型和管理器后,别忘了运行makemigrations和migrate命令,确保数据库 schema 同步哦!
备注:内容来源于stack exchange,提问作者Fenil Trivedi
相关产品推荐
相关产品推荐

