Создание собственного декоратора в Django для разных разрешений
Декораторы — невероятно полезные инструменты, которые позволяют вам динамически изменять функциональность функции, метода или класса без необходимости прямого использования подклассов или изменения исходного кода функции. Параметры декоратора login_required, require HTTP, require POST и другие необходимы при работе с представлениями Django.
Но есть также ситуации, когда мы хотим использовать наши собственные декораторы с уникальным дизайном, которые функционируют именно так, как мы хотим. Создание декораторов также может быть полезным, если вы применяете одну и ту же логику в нескольких местах и обнаружите, что удалить и добавить декоратор просто после того, как ваши изменения будут завершены.
Создайте собственный декоратор в Django
Здесь мы настроим механизм доступа учащихся к сайту. Чтобы учащиеся, учителя и директора не могли получить доступ к страницам, доступным для других пользователей. Этими привилегиями будут управлять настраиваемые декораторы, которые мы создадим, и мы будем возвращать различные результаты/ответы при каждом доступе к странице, чтобы мы могли увидеть различные способы перенаправления или возврата ответа для недоступной страницы.
Пошаговая реализация
Шаг 1: Создайте виртуальную среду и установите Django.
python -m venv custom_decorator_venv
Шаг 2. Создайте проект с именем CustomDecorator.
django-admin startproject CustomDecorator
Шаг 3. Перейдите в папку CustomDecorator, а затем создайте приложение с именем пользователя в проекте.
cd CustomDecorator
python manage.py startapp user
Структура файла
Это окончательная файловая структура после выполнения всех шагов.
Шаг 4: Добавьте пользовательское приложение в файл INSTALLED_APPS.
Python3
INSTALLED_APPS = [ "user.apps.UserConfig", "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", |
Шаг 5. Установите эту модель в качестве модели аутентификации по умолчанию в settings.py.
Python3
AUTH_USER_MODEL = "user.UserAccount" |
Шаг 6: Мы создадим UserAccountManager в качестве менеджера для модели UserAccount. В модели UserAccount будет пять функций: создать пользователя, создать суперпользователя, создать учителя, создать ученика и создать директора. Если логическое значение student равно True, пользователь является студентом; если логическое значение учителя равно True, пользователь является учителем; и то же самое верно для принципала.
пользователи/models.py
Python3
from django.db import modelsfrom django.contrib.auth.models import AbstractBaseUser, BaseUserManager class UserAccountManager(BaseUserManager): def create_user(self, email, username, password=None): if not email: raise ValueError("Email field is required !") if not username: raise ValueError("Username field is required !") if not password: raise ValueError("Passowrd field is required !") user = self.model( email=email, username=username ) user.set_password(password) user.save(using=self._db) return user def create_superuser(self, email, username, password): user = self.create_user( email=email, username=username, password=password) user.is_superuser = True user.is_staff = True user.is_admin = True user.save() return user def create_student(self, email, username, password): user = self.create_user(email, username, password) user.is_student = True user.save() return user def create_teacher(self, email, username, password): user = self.create_user(email, username, password) user.is_teacher = True user.save() return user def create_principal(self, email, username, password): user = self.create_user(email, username, password) user.is_principal = True user.save() return user class UserAccount(AbstractBaseUser): username = models.CharField(max_length=200, blank=False, null=False) email = models.CharField( max_length=200, blank=False, null=False, unique=True) is_active = models.BooleanField(default=True) is_staff = models.BooleanField(default=False) is_admin = models.BooleanField(default=False) is_superuser = models.BooleanField(default=False) is_student = models.BooleanField(default=False) is_teacher = models.BooleanField(default=False) is_principal = models.BooleanField(default=False) objects = UserAccountManager() USERNAME_FIELD = "email" def __unicode__(self): return str(self.username) def has_perm(self, perm, obj=None): return self.is_admin def has_module_perms(self, app_label): return True |
Шаг 7: Создайте папку templates/user в пользовательском приложении, в которой будут храниться следующие шаблоны:
- пользователь/шаблоны/пользователь/homePage.html
Это для главной страницы сайта.
HTML
<!DOCTYPE html> <html> <body> {% if messages %} {% for message in messages %} <div style = "color: red;">{{message}}</div> {% endfor %} <br> <br> {% endif %} {% if request.user.is_authenticated %} <h1> {{request.user.email}}</h1> <br> {% if request.user.is_student %} You are a student ... {% elif request.user.is_teacher %} You are a teacher ... {% elif request.user.is_principal %} You are a principal ... {% else %} You don"t have any privilege ... {% endif %} {% endif %} <br> <br> <a href = "{% url "user_urls:login-user" %}">Login </a> <br> <br> <a href = "{% url "user_urls:student-view" %}">Student View </a> <br> <br> <a href = "{% url "user_urls:teacher-view" %}">Teacher View</a> <br> <br> <a href = "{% url "user_urls:principal-view" %}">Principal View</a> <br> <br> </body></html> |
- пользователь/шаблоны/пользователь/loginView.html
Это домашняя страница, сообщающая, какой вы пользователь, и есть ссылки на другие страницы сайта, мы создадим эти ссылки и представления, а также отобразим сообщения, если они есть.
HTML
{% if messages %} {% for message in messages %} <div style = "color: red ;">{{message}}</div> <br> {% endfor %} {% endif %} <form method = "post"> {% csrf_token %}{{form.as_p}}<br><br><input type = "submit" value = "Login" /></form> |
- пользователь/шаблоны/пользователь/principalView.html
Это представление, доступ к которому будет иметь только пользователь, являющийся принципалом.
HTML
<h1> {{request.user.email}}</h1><br><h1> You are a principal and you can access the page !</h1> |
- пользователь/шаблоны/пользователь/studentView.html
Это представление студента, доступ к которому может получить только студент.
HTML
<h1> {{request.user.email}}</h1><br><h1> You are a student and you can access the page !</h1> |
- пользователь/шаблоны/пользователь/teacherView.html
Это точка зрения учителя, которую может видеть только учитель.
HTML
<h1> {{request.user.email}}</h1><br> <h1> You are a teacher and you can access the page !</h1> |
Шаг 8: user/decorators.py
Понимание концепции декораторов для этого проекта
Перед созданием нашего настоящего декоратора необходимо понять, как построить декоратор, это псевдокод/скелет декоратора.
У нас есть функция с именем test_function, которая принимает необходимые аргументы в зависимости от обстоятельств и возвращает True или False. Однако вы можете написать свою собственную функцию и определить любой оператор, который вам нравится. Декоратор либо принимает, либо отклоняет аргумент в зависимости от ситуации. @wraps из модуля functool берут имя функции, которое должно быть декорировано функцией-оболочкой.
_wrapped_view (request, *args, **kwargs) — это точное представление, в которое будет завернут декоратор, это как бы клон представления, вокруг которого будет завернуто декоратор, теперь вы можете выполнять любые действия, например, вы можете перенаправить , вернуть любой ответ или двигаться дальше.
Python3
from functool import wraps def test_function_works(*args, **kwargs): if args[0] == True: return True return False def some_decorator(*decorator_args , **decorator_kwargs): def decorator(view_function): @wraps(view_function) def _wrapped_view(request, *view_args, **view_kwargs): print("The required actions will be taken here ! Well, actually inside the _wrapped_view function") if not test_function_works(*arguments , **keyword_arguuments): print("The necessary operation that will be taken if the test case fails !") return view_function(request, *args, **kwargs) return _wrapped_view return decorator |