Python | User groups with Custom permissions in Django (original) (raw)
Last Updated : 31 May, 2022
Let’s consider a trip booking service, how they work with different plans and packages. There is a list of product which subscriber gets on subscribing to different packages, provided by the company. Generally, the idea they follow is the level-wise distribution of different products.
Let’s see the different packages available on tour booking service :
- Starter plan : In this package, subscriber will get the facility of non-AC bus travel and 1-day stay in a non-AC room only. Let’s say the trip is from Delhi to Haridwar(a religious place in Uttarakhand).
- Golden Plan : It will be somewhat costly than the Starter Plan. In this plan, subscriber will be given 2-day stay in a non-AC room, travelling in a AC bus and the trip will be from Delhi to Haridwar, Rishikesh and Mussoorie.
- Diamond Plan: This is the most costly plan, in which subscriber will be provided 3-day plan with AC bus and AC room stay, along with the trip to Haridwar, Rishikesh and Mussoorie and also trip to the Water Park.
Our main objective is to design and write code for the back-end in a very efficient way(following the DRY Principle).
There are multiple methods of implementing this in Django but the most suitable and efficient method is Grouping the Users and defining the permissions of these groups. User of that particular group will automatically inherit the permission of that particular group. Let’s define the User model first :
Create a Django application users. In models.py file, under ‘users’ app directory, write this code.
Python3
from
django.contrib.auth.models
import
AbstractUser
from
django.utils
import
timezone
from
django.db
import
models
class
User(AbstractUser):
`` first_name
=
models.CharField(_(
'First Name of User'
),
`` blank
=
True
, max_length
=
20
)
`` last_name
=
models.CharField(_(
'Last Name of User'
),
`` blank
=
True
, max_length
=
20
)
`` class
Meta:
`` permissions
=
(
`` (
"can_go_in_non_ac_bus"
,
"To provide non-AC Bus facility"
),
`` (
"can_go_in_ac_bus"
,
"To provide AC-Bus facility"
),
`` (
"can_stay_ac-room"
,
"To provide staying at AC room"
),
`` (
"can_stay_ac-room"
,
"To provide staying at Non-AC room"
),
`` (
"can_go_dehradoon"
,
"Trip to Dehradoon"
),
`` (
"can_go_mussoorie"
,
"Trip to Mussoorie"
),
`` (
"can_go_haridwaar"
,
"Trip to Haridwaar"
),
`` (
"can_go_rishikesh"
,
"Trip to Rishikesh"
),
After migrating the models written above, we have two option for making the group.
- Django Admin Panel : In Admin Panel you will see Group in bold letter, Click on that and make 3-different group named level0, level1, level3 . Also, define the custom permissions according to the need.
- By Programmatically creating a group with permissions: Open python shell using python manage.py shell.
Python3
from
django.contrib.auth.models
import
Group, Permission
from
django.contrib.contenttypes.models
import
ContentType
from
users.models
import
User
new_group, created
=
Group.objects.get_or_create(name
=
'new_group'
)
ct
=
ContentType.objects.get_for_model(User)
permission
=
Permission.objects.create(codename
=
'can_go_haridwar'
,
`` name
=
'Can go to Haridwar'
,
`` content_type
=
ct)
new_group.permissions.add(permission)
We will set different set of permissions in the same way to all the three groups. Until then, we have made groups and linked it with custom permissions.
Now, check that a particular user is accessing the appropriate functionality like, put a limit that level0 does not access the functionalities of level1 users or level2 user and so on. To do this, check the permission on every view function made.
To be very careful here, for the function based view we will simply use the custom decorator.
For example :
Python
@group_required
(
'level0'
)
def
my_view(request):
`` ...
For more details, refer this.
Things get a bit complex when we talk about class-based views, we can not simply just add a decorator function, but we have to make a permission-mixing class.
For example :
Python
class
GroupRequiredMixin(
object
):
`` ...............
`` ....Class Definition.....
class
DemoView(GroupRequiredMixin, View):
`` group_required
=
[u
'admin'
, u
'manager'
]
For more details, refer this.
References :
1. https://docs.djangoproject.com/en/1.11/topics/class-based-views/mixins/
2. http://bradmontgomery.blogspot.in/2009/04/restricting-access-by-group-in-django.html
3. https://simpleisbetterthancomplex.com/2015/12/07/working-with-django-view-decorators.html
4. https://micropyramid.com/blog/custom-decorators-to-check-user-roles-and-permissions-in-django/