0

Edit: Found the same scenario at this question: Use LoginRequiredMixin and UserPassesTestMixin at the same time

My view has 2 Mixins:

class FooView(LoginRequiredMixin, EmailVerifiedMixin, View):
        ...

EmailVerifiedMixin is a Mixin I wrote:

class EmailVerifiedMixin(UserPassesTestMixin):
    def test_func(self):
        return self.request.user.email_verified

    def handle_no_permission(self):
        return redirect(reverse("confirm_account"))

The problem is that when an Anonymous user goes to this view, they get redirected to confirm_account, rather than my login_url from LoginRequiredMixin's handle_no_permission(). See the MRO of this view:

>>> pprint(FooView.__mro__)
(<class 'foo_app.views.FooView'>,
 <class 'django.contrib.auth.mixins.LoginRequiredMixin'>,
 <class 'foo_app.views.EmailVerifiedMixin'>,
 <class 'django.contrib.auth.mixins.UserPassesTestMixin'>,
 <class 'django.contrib.auth.mixins.AccessMixin'>,
 <class 'django.views.generic.base.View'>,
 <class 'object'>)
>>> FooView.handle_no_permission
<function EmailVerifiedMixin.handle_no_permission at 0x7fbc46d8f1f0>

I think the EmailVerifiedMixin is just overwriting the LoginRequiredMixin's handle_no_permission()? How can I use both of these Mixins?

Just for clarity: The desired behavior is if the user is not logged in, redirect to login_url. If they are logged in, have them go through the EmailVerifiedMixin

David Jay Brady
  • 1,034
  • 8
  • 20

1 Answers1

0

I don't like it, but it works. Not going to accept my own answer here so please still answer if you know how to do what the question asked.

class EmailVerifiedMixin(LoginRequiredMixin, UserPassesTestMixin):

    def test_func(self):
        return self.request.user.email_verified

    def handle_no_permission(self):
        try:
            login_redirect = super().handle_no_permission()
            return login_redirect
        except PermissionDenied:
            return redirect(reverse("confirm_account"))

And just use EmailVerifixedMixin on the FooView now

David Jay Brady
  • 1,034
  • 8
  • 20