Creating decorator
We have created three functions ( student_test_function, teacher_test_function, principal_test_function ) which return True if the user is the following user in each case. These test_functions are to be used by decorators.
- student_access_only decorator: It wraps a view, if the currently logged-in user is not a student then he is returned a HttpResponse, that you are not a student and you cannot access the page.
- teacher_access_only decorator: It requires the input view_to_return, to which the user will be redirected if they are not teachers (we will generate the URLs).
- principal_access_only decorator: it takes a message which will be sent to a certain page telling that you are not a principal and you cannot access the page and then you will be redirected to the login page.
Python3
from functools import wraps from django.contrib import messages from django.shortcuts import redirect from django.http import HttpResponse def student_test_function(user): if user.is_student: return True return False def teacher_test_function(user): if user.is_teacher: return True return False def principal_test_function(user): if user.is_principal: return True return False def student_access_only(): def decorator(view): @wraps (view) def _wrapped_view(request, * args, * * kwargs): if not student_test_function(request.user): return HttpResponse("You are not a student and \ you are not allowed to access this page !") return view(request, * args, * * kwargs) return _wrapped_view return decorator def teacher_access_only(view_to_return = "user_urls:home-page" ): def decorator(view): @wraps (view) def _wrapped_view(request, * args, * * kwargs): if not teacher_test_function(request.user): messages.error(request, "You cannot access \ the teachers page !") return redirect(view_to_return) return view(request, * args, * * kwargs) return _wrapped_view return decorator def principal_access_only(message_to_deliver = "Not allowed to \ access the principal's page , login as principal !"): def decorator(view): @wraps (view) def _wrapped_view(request, * args, * * kwargs): if not principal_test_function(request.user): messages.error(request, message_to_deliver) return redirect( "user_urls:login-user" ) return view(request, * args, * * kwargs) return _wrapped_view return decorator |
Step 9: user/views.py
We have four views that just render out the templates.
Python3
from django.shortcuts import render from .decorators import ( student_access_only, teacher_access_only, principal_access_only ) def homePage(request, * args, * * kwargs): context = {} return render(request, "user/homePage.html" , context) @student_access_only () def studentView(request, * args, * * kwargs): context = {} return render(request, "user/studentView.html" , context) @teacher_access_only () def teacherView(request, * args, * * kwargs): context = {} return render(request, "user/teacherView.html" , context) @principal_access_only () def principalView(request, * args, * * kwargs): context = {} return render(request, "user/principalView.html" , context) |
Step 10: user/urls.py
These URLs help to route to the respective views.
Python3
from django.urls import path from user import views as user_views from django.contrib.auth.views import LoginView app_name = "user_urls" urlpatterns = [ path(" ", user_views.homePage, name=" home - page"), path( "login-user/" , LoginView.as_view(template_name = "user/loginView.html" ), name = "login-user" ), path( "student-view/" , user_views.studentView, name = "student-view" ), path( "teacher-view/" , user_views.teacherView, name = "teacher-view" ), path( "principal-view/" , user_views.principalView, name = "principal-view" ), ] |
Step 11: CustomDecorator/settings.py
Also, set up the LOGIN_REDIRECT_URL for the login in settings.py
Python3
LOGIN_REDIRECT_URL = "user_urls:home-page" |
Step 12: CustomDecorator/urls.py
Now set up the project urls.py to direct them to our user app.
Python3
from django.contrib import admin from django.urls import path, include urlpatterns = [ path( 'admin/' , admin.site.urls), path(" ", include(" user.urls ", namespace=" user_urls")), ] |
Step 13: Now, migrate the data to the database using the following command.
python manage.py makemigrations python manage.py migrate
Step 14: Open the Django shell and create three users, one student, one teacher, and one principal.
python manage.py shell
from user.models import UserAccount
UserAccount.objects.create_student(username = “student” , email = “studentmail@gmail.com” , password = “testing123”)
UserAccount.objects.create_teacher(username = “teacher” , email = “teachermail@gmail.com” , password = “testing123”)
UserAccount.objects.create_principal(username = “principal” , email = “principalmail@gmail.com” , password = “testing123”)
Step 19: Now run the server to test your project.
python manage.py runserver
Output:
Creating Custom Decorator in Django for different permissions
Decorators are incredibly helpful tools that allow you to dynamically change the functionality of a function, method, or class without having to utilize subclasses directly or modify the function’s source code. The decorator’s login_required, require HTTP methods, require POST, and others are needed when working with Django views.
But there are also situations where we want to utilize our own, uniquely designed decorators that function exactly how we want them to. Making decorators can also be useful if you apply the same logic in several places and find that it is simple to remove and add the decorator after your changes are complete.