Custom Decorators To Check User Roles And Permissions In Django

Reading Time : ~ .

A decorator is a function that takes another function and returns a newer, prettier version of that function.

To know more about decorators in python see here https://micropyramid.com/blog/programming-with-python-decorators/

The most common use of a decorator is the login_required. This decorator is used in conjunction with a view that restricts access to authenticated users only.

from django.contrib.auth.decorators import login_required

@login_required(login_url='/dashboard/')

def index(request):

    return render(request, 'index.html')


This decorator is very useful because we don’t have to actually change anything about my view to restrict access to it.

login required takes an optional argument login_url. If a user is authenticated, it successfully executes the function, 
if not it redirects the users to URL specified in the login_url option. If we don't mention login_url option, we must define login_url in settings.py

But the login_required decorator does not check when the logged in user is active or not. We can use the "user_passes_test" decorator to write our own custom decorators

from django.contrib.auth.decorators import login_required, user_passes_test

user_login_required = user_passes_test(lambda user: user.is_active, login_url='/')

def active_user_required(view_func):
    decorated_view_func = login_required(user_login_required(view_func))
    return decorated_view_func

@active_user_required
def index(request):
    return render(request, 'index.html')

Here user_passes_test decorator returns the value of is_active, which is a boolean that designates if the user is active.
and login_url parameter, which will redirect to this URL if the user is not active. So we can use active_user_required decorator to

If you want to execute the view according to the user role, we can write decorators using model methods


def is_recruiter(self):
    if str(self.user_type) == 'Recruiter':
        return True
    else:
        return False
rec_login_required = user_passes_test(lambda u: True if u.is_recruiter else False, login_url='/')

def recruiter_login_required(view_func):
    decorated_view_func = login_required(rec_login_required(view_func), login_url='/')
    return decorated_view_func

@recruiter_login_required
def index(request):
    return render(request, 'index.html')


Here is_recruiter is a model method which checks the user role. We are using the model method in the user_passes_test decorator. If user role satisfied, then it executes the function, otherwise, it redirects the home page

If you want to execute the view according to the user permission, we can write parameterized decorators using Django permissions
We can list user permissions in the user model metaclass.

class Meta:
    permissions = (
            ('blog_view', 'can view blog posts and categories'),
            ('blog_edit', 'can edit blog category and post'),
            ("support_view", "can view tickets"),
            ("support_edit", "can edit tickets"),
            ("activity_view", "can view recruiters, applicants, data, posts"),
            ("activity_edit", "can edit data"),
        )

def has_perm(self, perm, obj=None):
    try:
        user_perm = self.user_permissions.get(codename=perm)
    except ObjectDoesNotExist:
        user_perm = False
    if user_perm:
        return True
    else:
        return False

def permission_required(*perms):
    return user_passes_test(lambda u: any(u.has_perm(perm) for perm in perms), login_url='/')

@permission_required("activity_view", "activity_edit")
def index(request):
    return render(request, 'index.html')

Here we can pass user permissions values in decorator itself, and in the permission_required, we are checking user is having particular permission or not using for loop. If user don't have permits, it redirects the home page.

    By Posted On
SENIOR DEVELOPER at MICROPYRAMID

Need any Help in your Project?Let's Talk

Latest Comments
Related Articles
Check test coverage in code with Coveralls Swetha Naretla

Coverage: It is a tool used for measuring the effectiveness of tests, showing the percentage of your codebase covered by tests.
Test Coverage is an ...

Continue Reading...
How To Write Custom migrations in Django Shirisha Gaddi

This blog post will help you to get deeper into Django Migrations - how Migrations works and how to create or add our custom migrations. ...

Continue Reading...
Working with Django Plugins Vinisha Naladala

This blog describes about how to work with django-plugins. Django Plugin is a Simple Plugin Framework for Django. By using django-plugins, you can make your ...

Continue Reading...

Subscribe To our news letter

Subscribe to our news letter to receive latest blog posts into your inbox. Please fill your email address in the below form.
*We don't provide your email contact details to any third parties