Is it possible to combine PermissionRequiredMixin and LoginRequiredMixin?

I have some users who are allowed to see a specific view.

So that users can log in and complain about 403 Forbidden for those users who cannot see this login, I can use the following (as described here ):

 @permission_required('polls.can_vote', raise_exception=True) @login_required def my_view(request): ... 

It really works as expected. But all of my views are class based. Starting with Django 1.9 (finally!), There are tons of good mixins for doing things that were only possible through decorators. But...

 class MyClassView(LoginRequiredMixin, PermissionRequiredMixin, TemplateView): raise_exception = <???> permission_required = 'polls.can_vote' template_name = 'poll_vote.html' 

this does not work. Since the raise_exception flag raise_exception used by both LoginRequiredMixin and PermissionRequiredMixin , I cannot set it.

  • If raise_exception is True , a user who is not registered gets 403 Forbidden (which I don't want).
  • If raise_exception is False , a user who is not allowed to see the view will be redirected to the login page, which, since the user is logged in, will redirect to the page again. Creating a non-expert redirect cycle.

Of course, I could implement my own mixin, which behaves as I expected, but is there a way for Django to do this in the view itself? (not in urls.py )

+6
source share
3 answers

For many cases, an increase of 403 for unauthenticated users is the expected behavior. So yes, you need a custom mixin:

 class LoggedInPermissionsMixin(PermissionRequiredMixin): def dispatch(self, request, *args, **kwargs): if not self.request.user.is_authenticated(): return redirect_to_login(self.request.get_full_path(), self.get_login_url(), self.get_redirect_field_name()) if not self.has_permission(): # We could also use "return self.handle_no_permission()" here raise PermissionDenied(self.get_permission_denied_message()) return super(LoggedInPermissionsMixin, self).dispatch(request, *args, **kwargs) 
+5
source

I wanted to add a comment, but my reputation does not allow it. What about the next one? I feel like reading below?

Updated after comments

My reasoning: you basically write a modified dispatch from LoginRequiredMixin and just set raise_exception = True . PermissionRequiredMixin will raise PermissionDenied when the correct permissions are not executed

 class LoggedInPermissionsMixin(PermissionRequiredMixin): raise_exception = True def dispatch(self, request, *args, **kwargs): if not self.request.user.is_authenticated(): return redirect_to_login(self.request.get_full_path(), self.get_login_url(), self.get_redirect_field_name()) return super(LoggedInPermissionsMixin, self).dispatch(request, *args, **kwargs) 
+2
source

The simplest solution seems to be a custom mixin view. Something like that:

 class PermissionsMixin(PermissionRequiredMixin): def handle_no_permission(self): self.raise_exception = self.request.user.is_authenticated() return super(PermissionsMixin, self).handle_no_permission() 

Or simply use PermissionRequiredMixin , as usual, and put this handle_no_premission in each CBV.

0
source

All Articles