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