realnot
realnot

Reputation: 753

How to retrieve all permissions of a specific model in django?

By default each django model has 3 permissions (add, change, delete). In a model I can define my custom permission to adds more.

class Company(models.Model):
    owner = models.ForeignKey(User)
    name = models.CharField(max_length=64, unique=True)
    description = models.TextField(max_length=512)
    created_on = models.DateTimeField(auto_now_add=timezone.now)

    class Meta:
        permissions = (
            ("erp_view_company", "Can see the company information"),
            ("erp_edit_company", "Can edit the company information"),
            ("erp_delete_company", "Can delete the company"),
        )

When you migrate, these permissions are automatically created at DB level. How can you retrieve all the permissions from a model?

# retrieves the permissions
permissions = Permission.objects.filter(get_all_permissions_of_model_Company)
# adds permissions to group
group = Group.objects.create(name='foo', permissions=permissions)
# adds user to group
user.groups.add(group)

Upvotes: 14

Views: 15320

Answers (3)

AlanSE
AlanSE

Reputation: 2775

I wanted to achieve this without touching the database, using the Meta class instead. Django gives you everything you need, but it takes a little arm twisting.

codenames = [t[0] for t in Company._meta.permissions]
for action in Company._meta.default_permissions:
    codenames.append(f'{action}_{Company._meta.model_name}')
print(codenames)

This should give a coherent list like:

['erp_view_company',
 'erp_edit_company',
 'erp_delete_company',
 'add_company',
 'change_company',
 'delete_company',
 'view_company']

So in my case, there are many scenarios where I want a list of valid codenames to create a query, and it's not reasonable to have someone execute multiple queries in that process if it is performance-sensitive.

Upvotes: 1

Ernest
Ernest

Reputation: 2949

I would suggest you something like this:

all_permissions = Permission.objects.filter(content_type__app_label='app label', content_type__model='lower case model name')

Retrieving model's app_label:

Company._meta.app_label

Retrieving model's lower case name:

Company._meta.model_name

Also, you can retrieve a ContentType instance representing a model:

ContentType.objects.get_for_model(Company)

Since ContentType uses a cache, it is quite acceptable. Thus, there is another way to achieve what you need:

content_type = ContentType.objects.get_for_model(Company)
all_permissions = Permission.objects.filter(content_type=content_type)

Upvotes: 38

doniyor
doniyor

Reputation: 37904

you can check on codename field which will be something like: 'change_company' etc ...

model_name = 'company'
all_perms_on_this_modal = Permission.objects.filter(codename__contains=model_name)

Upvotes: 3

Related Questions