Search code examples
pythondjangopython-decorators

Django decorators to handle admin users redirection


I want normal users to be redirected to <address>/panel and need admins to be redirected to <adress>/admin. So what I did in views.py is something like:

from django.contrib.auth.decorators import login_required

@unauthenticated_user
def registration_view(request):
    ...

@unauthenticated_user
def login_view(request):
    ...

@login_required(login_url='login')
@allowed_users(allowed_roles=['admin'])
def admin_home_view(request):
    context = {}
    return render(request, 'account/admin/home-page.html', context)

@login_required(login_url='login')
@allowed_users(allowed_roles=['user'])
def user_home_view(request):
    context = {}
    return render(request, 'account/user/home-page.html', context)

Update here

And in decorators.py I have:

from django.http import HttpResponse
from django.shortcuts import redirect
from groups_manager.models import Group, GroupMemberRole, Member

def unauthenticated_user(view_func):
    def wrapper_func(request, *args, **kwargs):
        if request.user.is_authenticated:
            return redirect('panel')
        else:
            return view_func(request, *args, **kwargs)
    return wrapper_func

def allowed_users(allowed_roles=[]):
    def decorator(view_func):
        def wrapper_func(request, *args, **kwargs):
            allowed_role = allowed_roles[0]
            username = request.user.username
            member = Member.objects.get(username=username)
            roles = GroupMemberRole.objects.filter(groupmember__member=member)
            member_roles = []
            for role in roles:
                member_roles.append(role.label)
            if 'admin' in member_roles:
                ...
            elif 'user' in member_roles:
                ...
            else:
                return HttpResponse('you are not allowed')
        return wrapper_func
    return decorator

I want to know how I can redirect admin users to <address>/admin url. But admin users are redirected to /panel url.

My urls.py is:

urlpatterns = [
    path('admin', views.admin_home_view, name='admin'),


    path('panel', views.user_home_view, name='panel'),

    path('panel/register', views.registration_view, name='register'),
    path('panel/logout', views.logout_view, name='logout'),
    path('panel/login', views.login_view, name='login'),
]

Solution

  • You should take a look at django-braces because it is a great app for handling these type of user/auth scenarios with it's decorators and mixins (but this would require you to switch to class based views for the later).

    You could/should override django's LoginView which you can see here and do something like;

    from django.contrib.auth.views import LoginView as DjangoLogin
    from django.http import HttpResponseRedirect
    
    
    class LoginView(DjangoLogin):
        """ Custom Login """
    
        def form_valid(self, form):
            """Security check complete. Log the user in."""
            user = form.get_user()
            auth_login(self.request, user)
    
            # Do your permissions check here
            if user.is_staff:
                return HttpResponseRedirect('/admin')
            else:
                return HttpResponseRedirect('/panel')