Python | User groups with Custom permissions in Django

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 :

  1. 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).
  2. 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.
  3. 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.

filter_none

edit
close

play_arrow

link
brightness_4
code

# importing necessery django classes
from django.contrib.auth.models import AbstractUser
from django.utils import timezone
from django.db import models
  
# User class
class User(AbstractUser):
  
    # Define the extra fields
    # related to User here
    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)
                              
# More User fields according to need
  
    # define the custom permissions
    # related to User.
    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"),
  
# Add other custom permissions according to need.

chevron_right


 
After migrating the models written above, we have two option for making the group.

  1. Django Admin Pannel : 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.
  2. By Programmatically creating a group with permissions : Open python shell using python manage.py shell.
filter_none

edit
close

play_arrow

link
brightness_4
code

# importing group class from django
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
  
# import User model
from users.models import User 
  
new_group, created = Group.objects.get_or_create(name ='new_group')
  
# Code to add permission to group
ct = ContentType.objects.get_for_model(User)
  
# If I want to add 'Can go Haridwar' permission to level0 ?
permission = Permission.objects.create(codename ='can_go_haridwar',
                                        name ='Can go to Haridwar',
                                                content_type = ct)
new_group.permissions.add(permission)

chevron_right


 

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 :

filter_none

edit
close

play_arrow

link
brightness_4
code

@group_required('level0')
def my_view(request):
    ...

chevron_right


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 :

filter_none

edit
close

play_arrow

link
brightness_4
code

class GroupRequiredMixin(object):
    ...............
    ....Class Definition.....
  
  
class DemoView(GroupRequiredMixin, View):
  group_required = [u'admin', u'manager']
    
  # View code...

chevron_right


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/



My Personal Notes arrow_drop_up

Linux | Python | Django | Data Science | Blockchain | Politics | Philosophy

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.




Article Tags :

Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.