【Django】有關多使用者管理的一點小經驗分享

Frederic_Niu 發表於 2021-04-05

前言

最近,筆者因為需要開發一個系統作為畢設的展示,因此就產生了有關多使用者管理的問題。在這裡我把自己的需求重新闡明一下:能夠通過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獲取使用者即可,然後根據擴充套件屬性名來獲取擴充套件的特有屬性即可。