Создание собственного декоратора в 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 models from 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 |