Search code examples
djangodjango-viewsdjango-class-based-viewsdjango-permissions

Django UserPassesTestMixin confusion/questions?


I am currently working on an admin dashboard, which include specific views for company administrators only which are labeled as Business users.

The app is going to have about 10 views, and I had a few questions in regards to the UserPassesTestMixin

Basically, all of my views would include this,

def test_func(self):
    return self.request.user.user_type == 'Business'

To make sure the users are Business users I am protecting the views that way.

A couple questions that I am having trouble solving on my own are:

Now with that being repeated say 10 times, is there a cleaner way to do this, rather than having def test_func in every CBV?

The other question that comes up, if the user doesn't pass test, it redirects to the login page, which I don't really like either. These views are all returning json. If the user does not pass test, I would like to just send them to something like,

JsonResponse({'message': 'Only company administrators have access to this view'})

How would I able to change that redirect only if the user does not pass test? Keeping in mind that these views also inherit from LoginRequiredMixin as well, in which if the user is not logged in I want to keep the original redirect to the login page in tact.

Any help with this is very appreciated. This side of Django is something fairly new to me!


Solution

  • Now with that being repeated say 10 times, is there a cleaner way to do this, rather than having def test_func in every CBV?

    Yes, you can simply make a mixin that implements the check:

    from django.contrib.auth.mixins import UserPassesTestMixin
    
    class BusinessUserMixin(LoginRequiredMixin, UserPassesTestMixin):
        
        def test_func(self):
            return self.request.user.user_type == 'Business'
    
        def handle_no_permission(self):
            return JsonResponse(
                {'message': 'Only company administrators have access to this view'}
            )

    and then you use this mixin in your views, for example:

    class MyView1(BusinessUserMixin, ListView):
        # …
        pass
    
    class MyView2(BusinessUserMixin, DetailView):
        # …
        pass
    
    class MyView3(BusinessUserMixin, CreateView):
        # …
        pass

    if the user doesn't pass test, it redirects to the login page, which I don't really like either. These views are all returning json. If the user does not pass test, I would like to just send them to something like.

    You can override the handle_no_permission method as well, the view will return the result of this method as result when the test fails.