Django-------重写User模型
在 Django 中,重写自带的 auth 或 User 模型的原因通常涉及项目特定的需求和对用户数据管理的灵活性要求。以下是一些常见的原因:
- 自定义用户字段:
- Django 自带的 User 模型提供了基本的用户字段,如用户名、密码、邮箱等。但对于某些项目来说,这些字段可能不足以满足需求。例如,可能需要添加额外的用户信息,如姓名、电话号码、地址等。
- 通过重写 User 模型,可以添加自定义的字段,以便更好地存储和管理用户数据。
- 自定义用户认证:
- Django 的 auth 模块提供了用户认证功能,但默认情况下,它是基于用户名和密码的。在某些项目中,可能需要使用其他认证方式,如邮箱认证、手机短信认证或第三方社交账号认证。
- 重写 User 模型和相关的认证后端可以使项目支持自定义的认证逻辑。
- 扩展用户权限管理:
- Django 的权限管理系统允许为每个用户分配不同的权限,以控制他们对网站资源的访问。然而,在某些项目中,可能需要更复杂的权限管理逻辑,如基于角色的权限管理(RBAC)或基于声明的访问控制(ABAC)。
- 通过重写 User 模型和相关的权限管理逻辑,可以实现更复杂的权限管理需求。
- 与其他系统集成:
- 在一些项目中,可能需要将 Django 与其他系统集成,如 LDAP、Active Directory 或其他用户管理系统。
- 重写 User 模型和相关的认证后端可以使 Django 能够与这些系统集成,实现统一的用户管理和认证。
- 符合特定业务逻辑:
- 某些项目可能有特定的业务逻辑要求,如用户注册时必须填写某些字段、用户密码的加密方式等。
- 通过重写 User 模型和相关的逻辑,可以确保用户数据符合项目的特定业务逻辑。
- 优化数据库结构:
- 在某些情况下,可能需要优化数据库结构以提高性能或满足特定的数据关系要求。
- 重写 User 模型可以允许对数据库表结构进行自定义,以满足这些要求。
- 解决兼容性问题:
- 在一些旧版本的 Django 中,自带的 User 模型可能不支持某些新特性或与其他库存在兼容性问题。
- 通过重写 User 模型,可以解决这些兼容性问题,使项目能够使用最新的 Django 特性或与其他库兼容。
Django中自带的有auth和User模型:
class AbstractUser(AbstractBaseUser, PermissionsMixin):
"""
An abstract base class implementing a fully featured User model with
admin-compliant permissions.
Username and password are required. Other fields are optional.
"""
username_validator = UnicodeUsernameValidator()
username = models.CharField(
_("username"),
max_length=150,
unique=True,
help_text=_(
"Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only."
),
validators=[username_validator],
error_messages={
"unique": _("A user with that username already exists."),
},
)
first_name = models.CharField(_("first name"), max_length=150, blank=True)
last_name = models.CharField(_("last name"), max_length=150, blank=True)
email = models.EmailField(_("email address"), blank=True)
is_staff = models.BooleanField(
_("staff status"),
default=False,
help_text=_("Designates whether the user can log into this admin site."),
)
is_active = models.BooleanField(
_("active"),
default=True,
help_text=_(
"Designates whether this user should be treated as active. "
"Unselect this instead of deleting accounts."
),
)
date_joined = models.DateTimeField(_("date joined"), default=timezone.now)
objects = UserManager()
EMAIL_FIELD = "email"
USERNAME_FIELD = "username"
REQUIRED_FIELDS = ["email"]
class Meta:
verbose_name = _("user")
verbose_name_plural = _("users")
abstract = True
def clean(self):
super().clean()
self.email = self.__class__.objects.normalize_email(self.email)
def get_full_name(self):
"""
Return the first_name plus the last_name, with a space in between.
"""
full_name = "%s %s" % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
"""Return the short name for the user."""
return self.first_name
def email_user(self, subject, message, from_email=None, **kwargs):
"""Send an email to this user."""
send_mail(subject, message, from_email, [self.email], **kwargs)
但里面有一些方法实例的定义是在我们自己的项目中是用不到的,比如first_name、second_name
等等
所以我们要重写我们的User模型,以满足我们的具体项目的需要
class OAUser(AbstractBaseUser, PermissionsMixin):
"""
自定义的User模型
"""
realname = models.CharField( max_length=150,unique=False,)#OA项目需求,用于实名
email = models.EmailField( blank=False, unique=True ) #邮箱,以邮箱作为登录的凭证,所以不能为空
telephone = models.CharField( max_length=150,blank=True) #手机号,用于用户信息
#关注status,无需关注is_active
is_staff = models.BooleanField(default=True)
is_active = models.BooleanField(default=True)
status = models.IntegerField(choices=UserStatusChoices, default=UserStatusChoices.UNACTIVAE)
date_joined = models.DateTimeField(auto_now_add=True)
objects = OAUserManager()
EMAIL_FIELD = "email"
#USERNAME_FIELD: 用来鉴权的,会把authenticate的username参数,传给USERNAME_FIELD指定的字段
USERNAME_FIELD = "email" #这里用来鉴权的,因为username会重复,但email是唯一的
#REQUIRED_FIELDS:指定哪些字段是必须要传的,但不能包含USERNAME_FIELD和EMAIL_FIELD中已经设置的值
REQUIRED_FIELDS = ["realname", "password"]
继承自AbstractBaseUser, PermissionsMixin,在我们的重写的模型中增加了email.真实姓名,电话号码等等
由于我们需要获取我们的用户创建等等
objects = OAUserManager()
,然后再重写UserManaer模型,作为管理模型,实现用户的创建,和超级用户的创建等等
重写USerManager:
class OAUserManager(BaseUserManager):
use_in_migrations = True
def _create_user(self,realname, email, password, **extra_fields):
"""
创建用户
"""
if not realname:
raise ValueError("必须设置真实姓名") #返回错误信息
email = self.normalize_email(email) #对邮箱进行标准化
user = self.model(realname=realname, email=email, **extra_fields)
user.password = make_password(password)
user.save(using=self._db)
return user
def create_user(self, realname, email=None, password=None, **extra_fields):
"""
创建普通用户
"""
extra_fields.setdefault("is_staff", True)
extra_fields.setdefault("is_superuser", False)
return self._create_user(realname, email, password, **extra_fields)
def create_superuser(self, realname, email=None, password=None, **extra_fields):
"""
创建超级用户
"""
extra_fields.setdefault("is_staff", True)
extra_fields.setdefault("is_superuser", True)
extra_fields.setdefault("status", UserStatusChoices.ACTIVE)
if extra_fields.get("is_staff") is not True:
raise ValueError("超级用户必须设置is_staff=True.")
if extra_fields.get("is_superuser") is not True:
raise ValueError("超级用户必须设置is_superuser=True.")
return self._create_user(realname, email, password, **extra_fields)
然后在setting.py的最后用我们重新写的模型覆盖掉原django的模型
#覆盖dajngo自带的User模型
AUTH_USER_MODEL = 'oaauth.OAUser'
"""
语法是:
aap.重新写的模型名
"""
执行
python manage.py createsuperuser
进行超级用户的创建