Reputation: 1538
I created some code to differentiate between two usergroups in Django admin, resulting in showing all fields readonly or only some of them, which are set directly in the ModelAdmin class.
At first here is the code:
class PersonAdmin(admin.ModelAdmin):
readonly_fields = ('created_at','created_by',)
def get_form(self, request, obj=None, **kwargs):
if obj: # we are in edit mode
if request.user.is_superuser:
self.readonly_fields = ()
else:
for group in request.user.groups.all():
if str(group) == 'readonlyuser':
allfields = tuple(obj._meta.get_all_field_names())
self.readonly_fields = allfields
return super(PersonAdmin, self).get_form(request, obj, **kwargs)
I divide between the groups and set the fields accordingly. Everything works fine if users from the two groups are not logged in at the same time! After a 'readonly' user logged in, the adminuser will get all fields readonly too.
My inspections provided a solution also: If I put an additional if statement for the adminuser within the for block everything works as expected.
if str(group) == 'adminuser':
self.readonly_fields = PersonAdmin.readonly_fields
Why is that and what's happening there?
I have no special cache settings made and it happens on the dev server as well as on an Apache with WSGI.
From my understanding request.user.groups.all() should return all groups the currently logged in user belongs to. Where does Django get the allfields (readonly) from, if another user on a different IP and session match this if block?
Upvotes: 9
Views: 15007
Reputation: 239290
The ModelAdmin is only instantiated once for all requests that it receives. So when you define the readonly fields like that, you're setting it across the board permanently.
As long as you're running Django 1.2+, there's a get_readonly_fields
method you can use instead for exactly this purpose:
class MyModelAdmin(admin.ModelAdmin):
...
def get_readonly_fields(self, request, obj=None):
if request.user.is_superuser:
return super(MyModelAdmin, self).get_readonly_fields(request, obj)
else:
return ('created_at', 'created_by')
Remove the readonly_fields
attribute from your ModelAdmin
or set it to the fields that should be readonly for everyone. Then, in the else
block specify all the fields that should be readonly only for non-superusers.
Upvotes: 17
Reputation: 14190
Because the fields in Django Admin are being set (i.e cached) after being run the first time when the webserver was restarted. You could probably get around it by re-declaring the readonly_fields tuple. Something like this (untested):
def get_form(self, request, obj=None, **kwargs):
self.readonly_fields = ('created_at','created_by',)
# ...
Upvotes: 1