1

How to limit access to views in Django? My Account model is like this:

class Account(AbstractBaseUser):
      ...
      account_type    = models.PositiveSmallIntegerField(default=0, choices=ACCOUNT_TYPE_CHOICES)

I want to use a custom decorator to all my views based on account type but I don't know where to start.

Currently on my views, this is what I have done:

@login_required(login_url='/login/')
def dashboard(request, *args, **kwargs):
   if request.user.is_authenticated:
        if request.user.account_type == 1:
            return redirect('admin_page')
        else:
            ....

But this one is very repetitive.

rod james
  • 369
  • 3
  • 13

1 Answers1

2

You can create a custom decorator with user_passes_test method, like this:

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

user_limit = user_passes_test(lambda user: user.account_type != 1, login_url='admin_page')

def account_redirect(view_func):
    decorated_view_func = login_required(user_limit(view_func), login_url='/login/')
    return decorated_view_func

@account_redirect
def dashboard(request, *args, **kwargs):
    # rest of the code

Basically what I am doing is that if user's account type is 1, I am redirecting it to 'admin_page' url.

Also I found this medium article very useful for using user_passes_test method with dectorators.

ruddra
  • 50,746
  • 7
  • 78
  • 101
  • Shouldn't `login_required` be above `account_redirection` here? Otherwise there may be an `AttributeError` if the user is not logged in. – Abdul Aziz Barkat Feb 15 '21 at 07:40
  • Well order of the decorators in python are from bottom to top. So login required will execute before account redirection :) Reference: https://stackoverflow.com/questions/27342149/decorator-execution-order – ruddra Feb 15 '21 at 08:20
  • From what I understand `dashboard` is wrapped by `login_required` which is wrapped by `account_redirection()` meaning the first to execute would be the part of `account_redirection()`. The bottom up part means the result of the bottom ones is passed to the upper ones. So this would cause an `AttributeError` if user is not logged in. – Abdul Aziz Barkat Feb 15 '21 at 08:30
  • Yep, thanks for pointing that out. I found out from the login_required method's github code, that there is a way to pass on a function in login_required decorator. Now I am using that to prevent un authorized access to user_limit method. – ruddra Feb 15 '21 at 09:08