【Django】有关多用户管理的一点小经验分享

前言

最近,笔者因为需要开发一个系统作为毕设的展示,因此就产生了有关多用户管理的问题。在这里我把自己的需求重新阐明一下:能够通过Django自带的用户管理框架,实现多用户的管理,例如登录、登出、session、有效期等管理。
翻看很多同行写的文章,发现有关Django的多用户开发很多都含糊其词。主要原因是因为Django的django-admin框架的用户管理要么是用其自带的User类作为用户管理类,要么是自定义用户类别,并继承AbstractUser类。但是,无法实现两个或者多个类同时继承AbstractUser类,并且在settings.py文件中,AUTH_USER_MODEL也仅仅允许添加一个类。因此为了达到我们能够实现的需求,我有如下的设计思想,这个思想在后续的实践中证明可行。

实现

假设有用户类型A和用户类型B两中用户。

Step1:定义一个User类,使其继承AbstractUser类。

class User(AbstractUser):
    is_type1 = models.BooleanField(default=False)
    is_type2 = models.BooleanField(default=False)
        
    # 这里添加三类用户的除Django-admin框架的User类属性外的额外属性
    # 比如姓名
    name = models.CharField(max_length=100)

通过上面的代码,可以清楚的看到,User类中设置一个布尔标志,来对用户角色加以区分。
这样设计的好处就是将不同类型的用户进行了统一化。

Step2:定义用户类型1的用户类和用户类型2的用户类

#这里是用户类型1的定义
class User_Type_1(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
    # 一类用户的特有属性
    user_type_1_teyoushuxing = models.CharField(max_length=200)

    class Meta:
        db_table = 'tb_user_type_1'  # 修改表名
        verbose_name = '第一类用户管理'  # 管理系统后台显示名称
        verbose_name_plural = verbose_name  # 后台显示
        
#这里是用户类型2的定义
class User_Type_2(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
    # 二类用户的特有属性
    user_type_2_teyoushuxing = models.CharField(max_length=200)

    class Meta:
        db_table = 'tb_user_type_2'  # 修改表名
        verbose_name = '第二类用户管理'  # 管理系统后台显示名称
        verbose_name_plural = verbose_name  # 后台显示

我们可以看到,通过代码

user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)

将User和两类用户进行了绑定,这样做我们就实现了对User的一个扩展,同时实现了不同用户之前的互不干扰。

Step3:在注册创建用户时

# 创建用户
        try:
            user = User.objects.create_user(
                username=username,
                password=password,
                name=name
            )
            usertype_1 = User_Type_1.objects.create(user=user, user_type_1_teyoushuxing=user_type_1_teyoushuxing)
        except DatabaseError as e:
            logger.error(e)
            return HttpResponseBadRequest('注册失败')

Step4:在登录用户时

from django.contrib.auth import authenticate
    # 默认认证方法是针对username字段进行用户名的判断
    user = authenticate(username=username, password=password)
    if user is None:
        return HttpResponseBadRequest('用户名或者密码错误')

直接使用内置的authenticate获取用户即可,然后根据扩展属性名来获取扩展的特有属性即可。