how to add Permissions in Django to Models and Test it using the shell

21,838

In the example you gave, I would expect emp.has_perm('myappname.is_member') to indeed be False. Unless you explicitly give the new Employer object the is_member permission, it won't have it.

To programmatically give it the permission you need to get the actual permission object and add it to the Employer's user_permissions:

from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType

content_type = ContentType.objects.get_for_model(Employer)
permission = Permission.objects.get(content_type=content_type, codename='is_member')

emp = Employer.objects.create(blablabla)
emp.save()
emp.user_permissions.add(permission)

To test it in the shell, you may need to delete the permission cache that is created for each user- otherwise has_perm may not reflect the actual permissions:

delattr(emp, '_perm_cache')

Responding to your questions:

If you want every single Employer to have the is_member permission there are a few options:

  1. Override the save method of Employer to check if there is no self.pk (which means it is a new object, and create the permission as I showed above after saving. Not very pretty, but it would work.

  2. Write your own authentication backend. If the permission code is 'is_member' and the User has an Employer instance, return True

  3. Don't use permissions. The permission system is designed for you to be able to dynamically grant and revoke permissions. If you only care whether a User is an Employer- then test for that. Don't complicate it by using permissions.

Share:
21,838
Karim Tarek
Author by

Karim Tarek

Updated on December 10, 2020

Comments

  • Karim Tarek
    Karim Tarek over 3 years

    I added the Meta class in my model and synchronized the DB then created an object in the shell it returns false so i really cant understand where is the error or what is missing is there some sort of configuration maybe in some other files ..

    class Employer(User): # Employer inherits from User
        employer_verified = models.BooleanField(default=False)
    
        class Meta:
            permissions = (
                ("is_member", "Friendly permission description"),
            )
    
    emp = Employer.objects.create(blablabla)
    emp.save()
    emp.has_perm('myappname.is_member')
    
  • Karim Tarek
    Karim Tarek about 12 years
    ok if i want to add the permission just to the model meaning that every object created from that model have this permissions what should i do in the model??? excuse me .. but i am very confused
  • dgel
    dgel about 12 years
    That's not how permissions work. Adding the is_member permission doesn't mean that every Employee will have that permission. It means that any Employee has the option of having that permission.
  • Mentakatz
    Mentakatz over 11 years
    Excellent answer. +1 for mentioning delattr(emp, '_perm_cache'), I was having troubles while playing with permissions in the shell.
  • Mentakatz
    Mentakatz over 11 years
    One more, thing. There's also a _group_perm_cache attribute that you need to delete in case your user instance is inheriting permissions from groups. It may be easier to simply reload the user with something like u = User.objects.get(username='username'), that's what a test in django.contrib.auth does.