tags:

views:

41

answers:

2

When using the shell, this confused me (the permissions did not reflect changes):

>>> user = User.objects.get(username='test')
>>> user.get_all_permissions()
set([])
>>> p = Permission.objects.get(codename="add_slide")
>>> user.user_permissions.add(p)
>>> user.save()
>>> user.get_all_permissions()
set([])
>>> user = User.objects.get(username='test')
>>> user.get_all_permissions()
set([u'slides.add_slide'])

Why did the user object not update on save?
Is there a way save and update the object?

+2  A: 

Django doesn't update in-memory objects when on-disk objects change. Your first user still looks as it does when it was read from disk.

Ned Batchelder
So that explains what is happening but not really why? or the best way to update in-memory objects with on-disk changes?
The example you gave is kind of a special case because the `get_all_permissions()` method, which is a `User` model-specific method, happens to use caching. If you use the more generic Django model methods/properties, you'll find that they behave more intuitively and will update when you would expect them to.
Aram Dulyan
A: 

This is happening because User has a many2many relationship with Permission, so when you do user.user_permissions.add(p), the "auth_user" table does not get updated. Instead, its the "through" table for that relationship ("auth_user_user_permissions") that gets updated. In fact, you don't need to call user.save() at all.

The get_all_permissions() method appears to be using cached data, so if you want the latest changes, use:

user.user_permissions.all()

Note that this will return a list of Permission objects, so if you want a list of codenames in the exact same format as a get_all_permissions() call (not sure why you would though), you can do this:

set(user.user_permissions.values_list('codename', flat=True))
Aram Dulyan