haki
haki

Reputation: 9769

Django 1.7 - Adding permissions programmatically does not work as expected

What is going on here ?

> from django.contrib.auth.models import Permission
> from django.contrib.contenttypes.models import ContentType
> p = Permission.objects.filter(
    content_type = ContentType.objects.get_for_model(Transaction)
).get(
    codename = 'add_transaction'
)
> user.user_permissions.add(p)

> user.user_permissions.all()
[<Permission: myapp | Transaction | Can add Transaction>]
> user.get_all_permissions()
set([])
> user.has_perm('add_transaction')
False
> user.has_perm('myapp.add_transaction')
False

am i missing a save here somewhere ?

Upvotes: 2

Views: 2444

Answers (3)

worsht
worsht

Reputation: 11

dgel's answer is correct but incomplete. Both _perm_cache and _user_perm_cache need to be cleared to force a full reload.

for attr in ('_perm_cache', '_user_perm_cache'):
    delattr(user, attr)

Upvotes: 0

Alasdair
Alasdair

Reputation: 308999

The ModelBackend caches the permissions on the user object. The Django docs suggest that you reload the user from the db after changing the permissions.

user.user_permissions.add(p)
user = User.objects.get(pk=user.pk)

Upvotes: 5

dgel
dgel

Reputation: 16806

I believe user instances have a permissions cache that is populated when it is first pulled from the DB. Try deleting the cache before calling has_perm:

delattr(user, '_perm_cache')

After that, has_perm should work as expected. Normally this isn't an issue as you rarely add then immediately test for permissions on the same user instance (without pulling it from the DB again). Definitely can trip you up when you're testing in the python shell though.

Upvotes: -1

Related Questions