在Python Django中创建多种用户类型并使用代理模型

在Python Django中创建多种用户类型并使用代理模型

在这篇文章中,我们将了解代理模型的概念,以及根据你在Django中的应用需求实现多种用户类型。

什么是Django中的代理模式

一个继承的代理模型可以有一些额外的功能、方法,以及与创建者或程序员所定义的父模型不同的行为。这在一些情况下可能很有用,比如有多种类型的用户从同一个用户模型继承,为代理(新继承的模型)定义新的功能,而这些功能只为代理(新继承的模型)使用,等等。新的字段不能被添加到代理模型中,代理模型的限制是你不能在那里有自定义字段。

创建一个代理模型的属性:

  • 代理模型正好可以继承自一个非抽象的模型类。
  • 它不能继承于多个非抽象模型类,因为它不能提供数据库中不同表中的行之间的连接。
  • 它可以继承自任何数量的抽象类模型。
  • 代理模型可以继承自任何数量的具有相同的非抽象父类的代理模型。

在Django中可以用代理模型做什么

  • 我们可以通过以下方式改变模型的Pythonic行为,比如改变排序,用不同于父类的名字注释模型,等等。
  • 我们可以有一个代理模型,并有一个定制的query_set,根据模型获得相关的数据。
  • 我们可以有各种方法、属性和功能,这些都是该模型所特有的。
  • 我们可以创建多种类型的用户,这些用户继承自你的基本用户模型,他们都可以登录、认证,并执行不同的功能。

文件结构:

在Python Django中创建多种用户类型并使用代理模型

一步一步实现

第1步:创建一个名为ProxyModel.的Django项目。

django-admin startproject ProxyModel

第2步:移动到项目文件夹,然后创建一个名为proxymodelapp的应用程序。

python manage.py startapp proxymodelapp

第3步:创建应用程序后,进入setting.py并在INSTALLED_APPS中注册该应用程序。

INSTALLED_APPS = [
    # add to the installed apps .  
    'proxymodelapp.apps.ProxymodelappConfig', 
    
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

第4步:ProxyModel项目设置URL。

在Python Django中创建多种用户类型并使用代理模型

第5步:为proxymodelapp应用程序设置URL。

在Python Django中创建多种用户类型并使用代理模型

第6步:将代码粘贴到proxymodelapp/views.py中。

from django.shortcuts import render
  
def homePage(request) : 
    return render(request ,  "proxymodelapp/homePage.html" )

第7步:我们将创建一个自定义的用户名为UserAccount,其对象名为UserAccountManager,具有字段和权限。它将给不同的用户提供权限。在这里,我们将创建两种类型的用户:教师和学生,除了模型中的基本字段,我们还将添加两个字段,即is_teacheris_student,因为它们不是必需的,但对于小问题,这可能是有帮助的。

proxymodelapp/models.py

from django.db import models
from django.contrib.auth.models import AbstractBaseUser , BaseUserManager
  
class UserAccountManager(BaseUserManager):
    def create_user(self , email , password = None):
        if not email or len(email) <= 0 : 
            raise  ValueError("Email field is required !")
        if not password :
            raise ValueError("Password is must !")
          
        user = self.model(
            email = self.normalize_email(email) , 
        )
        user.set_password(password)
        user.save(using = self._db)
        return user
      
    def create_superuser(self , email , password):
        user = self.create_user(
            email = self.normalize_email(email) , 
            password = password
        )
        user.is_admin = True
        user.is_staff = True
        user.is_superuser = True
        user.save(using = self._db)
        return user
      
class UserAccount(AbstractBaseUser):
    class Types(models.TextChoices):
        STUDENT = "STUDENT" , "student"
        TEACHER = "TEACHER" , "teacher"
          
    type = models.CharField(max_length = 8 , choices = Types.choices , 
                            # Default is user is teacher
                            default = Types.TEACHER)
    email = models.EmailField(max_length = 200 , unique = True)
    is_active = models.BooleanField(default = True)
    is_admin = models.BooleanField(default = False)
    is_staff = models.BooleanField(default = False)
    is_superuser = models.BooleanField(default = False)
      
    # special permission which define that
    # the new user is teacher or student 
    is_student = models.BooleanField(default = False)
    is_teacher = models.BooleanField(default = False)
      
    USERNAME_FIELD = "email"
      
    # defining the manager for the UserAccount model
    objects = UserAccountManager()
      
    def __str__(self):
        return str(self.email)
      
    def has_perm(self , perm, obj = None):
        return self.is_admin
      
    def has_module_perms(self , app_label):
        return True
      
    def save(self , *args , **kwargs):
        if not self.type or self.type == None : 
            self.type = UserAccount.Types.TEACHER
        return super().save(*args , **kwargs)

代码解释:

  • 在UserAccount模型中,创建了一个新的类Types(models.TextChoices),它将为我们提供选择UserAccount内部的代理模型的用户类型。
  • 创建了一个字段类型,告诉用户的类型,默认设置为教师,电子邮件字段对于一个认证系统来说是唯一的。这里我们定义了3个字段,即is_superuser, is_admin, and is_staff,这为用户提供了权限。
  • 创建了两个新的字段is_student和is_teacher,它们只是布尔字段,告诉用户是教师还是学生。
  • 在保存时,如果没有为用户定义类型,则将其设置为教师。
  • 我们还创建了两个函数create_user和create_superuser,帮助创建具有不同权限的用户和超级用户。这个方法create_user将被用于我们的代理模型来创建用户,这样做是因为在代理模型中没有办法对密码进行散列。

第8步:在setting.py中设置认证模型,该模型将用于所有工作。

settings.py

AUTH_USER_MODEL = "proxymodelapp.UserAccount"

在Python Django中创建多种用户类型并使用代理模型

第9步:在创建了用户认证模型后,主要的任务是用代理模型创建多个用户类型,并配备各自的管理器,如果我们不为代理模型创建管理器,它们将继承父模型。在models.py中添加两个模型。

proxymodelapp/models.py

class StudentManager(models.Manager):
    def create_user(self , email , password = None):
        if not email or len(email) <= 0 : 
            raise  ValueError("Email field is required !")
        if not password :
            raise ValueError("Password is must !")
        email  = email.lower()
        user = self.model(
            email = email
        )
        user.set_password(password)
        user.save(using = self._db)
        return user
      
    def get_queryset(self , *args,  **kwargs):
        queryset = super().get_queryset(*args , **kwargs)
        queryset = queryset.filter(type = UserAccount.Types.STUDENT)
        return queryset    
        
class Student(UserAccount):
    class Meta : 
        proxy = True
    objects = StudentManager()
      
    def save(self , *args , **kwargs):
        self.type = UserAccount.Types.STUDENT
        self.is_student = True
        return super().save(*args , **kwargs)
      
class TeacherManager(models.Manager):
    def create_user(self , email , password = None):
        if not email or len(email) <= 0 : 
            raise  ValueError("Email field is required !")
        if not password :
            raise ValueError("Password is must !")
        email = email.lower()
        user = self.model(
            email = email
        )
        user.set_password(password)
        user.save(using = self._db)
        return user
        
    def get_queryset(self , *args , **kwargs):
        queryset = super().get_queryset(*args , **kwargs)
        queryset = queryset.filter(type = UserAccount.Types.TEACHER)
        return queryset
      
class Teacher(UserAccount):
    class Meta :
        proxy = True
    objects = TeacherManager()
      
    def save(self  , *args , **kwargs):
        self.type = UserAccount.Types.TEACHER
        self.is_teacher = True
        return super().save(*args , **kwargs)

代码解释:

注意,我们通过继承UserAccount创建了Student和Teacher模型,然后我们将代理关键字设置为True,以便将模型归类为代理,并且我们重写了保存函数,在这里我们将UserAccount的类型设置为它们各自的类型,并在每次保存函数时保存它。这是因为你可能从管理面板上改变它,它将改变为另一种类型,以克服这种情况,每次都要保存该类型。我们已经为教师和学生模型创建了各自的管理器,返回各自模型的查询集,其中包含各自类型的对象。

在每个用户、教师和学生的管理者中,我们都添加了create_user方法,用来创建学生和教师。

第10步:如果你想只改变或设置一次类型,请在保存函数中使用这段代码,而不是上述保存函数的代码片段。

# for teacher snippet
def save(self  , *args , **kwargs):
    if not self.id or self.id == None : 
        self.type = UserAccount.type.TEACHER
    return super().save(*args , **kwargs)
    
# for student snippet 
def save(self  , *args , **kwargs):
    if not self.id or self.id == None : 
        self.type = UserAccount.type.STUDENT
    return super().save(*args , **kwargs)

第11步:确保将所有模型注册到管理面板。

在Python Django中创建多种用户类型并使用代理模型

第12步:在cmd中写下以下命令,将数据迁移到数据库。

python manage.py makemigrations
python manage.py migrate

在Python Django中创建多种用户类型并使用代理模型

第13步:现在创建一个超级用户,他可以登录到应用程序并可以看到各种功能,为此,我们将创建一个超级用户,电子邮件:testingmail@gmail.com,密码为123。

python manage.py createsuperuser

第14步:移动到终端中的Django shell。同时,我们将从Django shell中创建两种类型的多个用户。

python manage.py shell

在这里,我们在数据库中创建了4个用户,这些用户可以登录并拥有多种功能。

from proxymodelapp.models import *
user1 = Teacher.objects.create_user(
  email = "teachermailone@gmail.com" , password = "password")
user1.save()
user2 = Teacher.objects.create_user(
  email = "teachermailtwo@gmail.com" , password = "password")
user2.save()
user3 = Student.objects.create_user(
  email = "studentmailone@gmail.com" , password = "password")
user3.save()
user4 = Student.objects.create_user(
  email = "studentmailtwo@gmail.com" , password = "password")
user4.save()

第15步:为登录页面创建一个HTML页面。这个模板有助于通过输入电子邮件及其密码来登录用户。随着用户的登录,它被重定向到主页。

proxymodelapp/templates/proxymodelapp/loginPage.html

<!DOCTYPE html>
<html>
  <body>
    <form method="post">
      {% csrf_token %}
      {{form.as_p}}
      <br />
      <input type="submit" value="Submit" />
    </form>
  </body>
</html>

第16步:为主页创建一个HTML页面。这个模板显示谁在登录,他的电子邮件是什么,他的用户类型是什么。如果用户经过认证,将显示详细信息。

proxymodelapp/templates/proxymodelapp/homePage.html

<!DOCTYPE html>
<html>
  <body>
    <hr>
    <br>
    {% if request.user.is_authenticated %}
    The current_user is  : {{request.user.email}}
    <br>
    <br>
    The type of the user is  : {{request.user.type}}
    {% endif %}
    <br />
    <br />
    <a href="{% url 'login-user' %}"> Login </a>
    <br />
    <hr>
  </body>
</html>

输出:这三种都是不同的模式,你可以从任何一种模式中登录。

在Python Django中创建多种用户类型并使用代理模型

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程