How to create a decorator for checking groups in Django
Sometimes, in the Django framework, it needs to wrap a view function into a decorator, that checks to contain if a user is in certain groups.
There are several requirements for our decorator:
- Ability to checking multiple groups at the same time
- Ability to changing a list of the groups in decorator arguments
- The decorator can contain some custom behavior. For example, only admins might know about existing some pages, other users getting 404 error.
Let`s create a module for decorators, name it “decorators.py” and write a simple decorator. That decorator checks to contain if a user in the “admin” group. If the check was not passed, then we return 404.
We can use this decorator like this in views.py:
@check_user_able_to_see_pagedef hidden_page(request):
....
There is a problem. If we want to add permission to the page for another group, then we need to change our decorator or create a new one. If we have several pages and each page needs to have a custom group check, then we need to create multiple decorators.
A decorator takes just one argument: the function to be decorated. There is no way to pass on other arguments. Let`s create a decorator factory. A decorator factory is a function that returns a decorator.
Thus, you can use it like:
@check_user_able_to_see_page("admin")
def hidden_page(request):
....
or
@check_user_able_to_see_page("manager")
def hidden_page(request):
....
or even
@check_user_able_to_see_page("admin", "manager")
def hidden_page(request):
....
It is a good variant, but let`s add some beautiful things. Create a module with an enumeration of groups:
# constants.py
from enum import Enumclass Group(Enum):
admin = "Administrator"
manager = "Manager"
Rewrite the decorator:
Then you can use it like:
from .constants import Group@check_user_able_to_see_page(Group.admin)
def hidden_page(request):
...