Создание нескольких типов пользователей и использование прокси-моделей в Python Django

Опубликовано: 14 Декабря, 2022

В этой статье мы поймем концепцию прокси-модели и реализацию нескольких типов пользователей в зависимости от требований вашего приложения в Django.

Что такое прокси-модель в Django?

Унаследованная прокси-модель может иметь несколько дополнительных функций, методов и поведение, отличное от родительской модели, как определено создателем или программистом. Это может быть полезно в таких ситуациях, как наличие нескольких типов пользователей, унаследованных от одной и той же пользовательской модели, определение новых функций для прокси-сервера (новая унаследованная модель), которые предназначены только для использования прокси-сервером (новая унаследованная модель) и так далее. В прокси-модели нельзя добавлять новые поля, ограничение прокси-модели в том, что у вас не может быть там настраиваемых полей.

Свойства для создания прокси-модели:

  • Прокси-модель может точно наследоваться от одного неабстрактного класса модели.
  • Он не может наследоваться от нескольких неабстрактных классов моделей, поскольку не может обеспечивать соединения между строками в разных таблицах базы данных.
  • Он может наследовать любое количество моделей абстрактных классов.
  • Прокси-модель может наследоваться от любого количества прокси-моделей, имеющих один и тот же неабстрактный родительский класс.

Что можно сделать с прокси-моделями в Django?

  • Мы можем изменить питоническое поведение модели, например, изменить порядок, аннотировать модель именем, отличным от родителя, и т. д.
  • У нас может быть прокси-модель с настроенным query_set для получения соответствующих данных в соответствии с моделью.
  • У нас может быть множество методов, свойств и функций, уникальных для этой модели.
  • Мы можем создать несколько типов пользователей, которые наследуют вашу базовую пользовательскую модель, и все они могут входить в систему, аутентифицироваться и выполнять различные функции.

Структура файла

Пошаговая реализация

Шаг 1: Создайте проект Django с именем ProxyModel.

django-admin startproject ProxyModel

Шаг 2: Перейдите в папку проекта, затем создайте приложение с именем proxymodelapp.

python manage.py startapp proxymodelapp

Шаг 3: После создания приложения перейдите в файл settings.py и зарегистрируйте приложение в INSTALLED_APPS.

Python3




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: Установите URL-адрес для проекта ProxyModel .

Шаг 4: Установите URL для приложения proxymodelapp.

Шаг 5: Вставьте код в proxymodelapp/views.py

Python3




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

Шаг 6: Мы создадим собственное имя пользователя как UserAccount с его объектом с именем UserAccountManager с полями и разрешениями. Это даст разрешение разным пользователям. Здесь мы создадим два типа пользователей: Учитель и Ученик, и добавим в модель еще два поля, помимо основных полей, — это is_teacher и is_student , поскольку они не требуются, но для незначительных проблем это может быть полезно.

проксимодельприложение/models.py

Python3




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.
  • Создан тип поля, указывающий тип пользователя, по умолчанию установлено значение TEACHER, а поле электронной почты уникально для системы аутентификации. Здесь мы определили 3 поля, т.е. is_superuser, is_admin и is_staff, это предоставляет разрешения для пользователей.
  • Созданы два новых поля is_student и is_teacher , которые являются просто логическими полями, которые сообщают, является ли пользователь учителем или учеником.
  • При сохранении, если у пользователя нет определенного типа, установите для него значение TEACHER.
  • Мы также создали две функции create_user и create_superuser , которые помогают создавать пользователей и суперпользователей с разными разрешениями. Этот метод create_user будет использоваться в наших прокси-моделях для создания пользователей, это сделано потому, что в прокси-моделях нет возможности хэшировать пароль.

Шаг 7: Установите модель аутентификации в settings.py, которая будет использоваться для всей работы.

settings.py

AUTH_USER_MODEL = "proxymodelapp.UserAccount"

Шаг 8: После создания модели аутентификации пользователя основная задача состоит в том, чтобы создать несколько типов пользователей с моделью прокси с их соответствующими менеджерами, если мы не создадим менеджеров для наших моделей прокси, они будут наследоваться от родительской модели. В models.py добавьте две модели.

проксимодельприложение/models.py

Python3




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)

Объяснение кода:

Обратите внимание, что мы создали модель «Студент и Учитель» , унаследовав учетную запись пользователя , а затем установили для ключевого слова прокси значение «Истина», чтобы классифицировать модель как прокси, и мы переопределили функцию сохранения, в которой мы устанавливаем тип учетной записи пользователя. чтобы быть их соответствующими типами и сохранять его каждый раз, когда сохраняется функция. Это потому, что вы можете изменить его из панели администратора, и он изменит его на другой тип, чтобы преодолеть это, сохраняя тип каждый раз. Мы создали соответствующие менеджеры для моделей «Учитель» и «Ученик », которые возвращают набор запросов соответствующих моделей, содержащих объекты соответствующих типов.

В менеджерах каждого из пользователей, Учителя и Ученика мы добавили метод create_user , который используется для создания ученика и учителя.

Шаг 9: Если вы хотите изменить или установить тип только один раз, используйте этот код для функции сохранения вместо приведенного выше фрагмента кода для функции сохранения.

Python3




# 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)

Шаг 8: Обязательно зарегистрируйте все модели в панели администратора.

Шаг 10: В cmd напишите следующие команды для переноса данных в базу данных.

python manage.py makemigrations
python manage.py migrate

Шаг 11: Теперь создайте суперпользователя, который сможет войти в приложение и увидеть его функции, для этого мы создадим суперпользователя с адресом электронной почты: testingmail@gmail.com и паролем 123.

python manage.py createsuperuser

Шаг 12: Перейдите в оболочку Django в терминале. Также мы создадим несколько пользователей обоих типов из оболочки Django.

python manage.py shell

Здесь мы создали 4 пользователя в базе данных, и они могут входить в систему и иметь несколько функций.

Python3




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()

Шаг 13: Создайте HTML-страницу для страницы входа. Этот шаблон помогает авторизоваться пользователю, введя адрес электронной почты и его пароль. и когда пользователь входит в систему, он перенаправляется на домашнюю страницу.

proxymodelapp/templates/proxymodelapp/loginPage.html

HTML