Reputation: 370
Views.py
class templateList(PermissionRequiredMixin, TemplateView):
permission_required = 'accounts.template_all'
def get(self, request, *args, **kwargs):
#view logic
print(self.request.user.has_perms('accounts.template_all'))
return render(request, template_name, context)
accounts/models.py
class User(AbstractBaseUser, PermissionsMixin):
# some fields here
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
permissions = (
("template_all", "access to all templates"),
)
ViewName.___mro____
(<class 'template.views.templateList'>, <class 'django.contrib.auth.mixins.PermissionRequiredMixin'>, <class 'django.contrib.auth.mixins.AccessMixin'>, <class 'django.views.generic.base.TemplateView'>, <class 'django.views.generic.base.TemplateResponseMixin'>, <class 'django.views.generic.base.ContextMixin'>, <class 'django.views.generic.base.View'>, <class 'object'>)
self.request.user.has_perms('accounts.template_all')
in views.py returns the correct boolean value, however, self.has_permission()
returns True every time. permission_required
has no effect, and the user is still able to see the page even when the print returns false. self.get_permission_required
alos returns the correct value. Help appreciated.
Upvotes: 2
Views: 8804
Reputation: 476557
In short: the PermissionRequiredMixin
baseclass should be placed before the TemplateView
baseclass, such that the MRO (Method Resolution Order) is correct, and dispatch points to the override of the PermissionRequiredMixin
.
A PermissionRequiredMixin
patches the dispatch(..)
method (well it adds an extra check that looks if the user has the proper permissions). Here however you have placed the subclasses in an order that results in the fact that the dispatch(..)
function is the one from the View
class.
Indeed, if we take a look at the MRO, we see:
>>> ViewName.__mro__
(<class 'ViewName'>, <class 'django.views.generic.base.TemplateView'>, <class 'django.views.generic.base.TemplateResponseMixin'>, <class 'django.views.generic.base.ContextMixin'>, <class 'django.views.generic.base.View'>, <class 'django.contrib.auth.mixins.PermissionRequiredMixin'>, <class 'django.contrib.auth.mixins.AccessMixin'>, <class 'object'>)
and if we take a look at the method that is called when we call .dispatch(..)
, we see:
>>> ViewName.dispatch
<function View.dispatch at 0x7f169e8f6620>
In order to let the mixin override the original .dispatch(..)
function, we need to put it first in the base classes, like:
# PermissionRequiredMixin is put before TemplateView
class ViewName(PermissionRequiredMixin, TemplateView):
permission_required = 'accounts.action_all'
# ...
We then see that:
>>> ViewName.__mro__
(<class 'ViewName'>, <class 'django.contrib.auth.mixins.PermissionRequiredMixin'>, <class 'django.contrib.auth.mixins.AccessMixin'>, <class 'django.views.generic.base.TemplateView'>, <class 'django.views.generic.base.TemplateResponseMixin'>, <class 'django.views.generic.base.ContextMixin'>, <class 'django.views.generic.base.View'>, <class 'object'>)
>>> ViewName.dispatch
<function PermissionRequiredMixin.dispatch at 0x7f168b41d620>
Upvotes: 7