Ultimately, my goal is to extend Django ModelAdmin to provide permissions at the field level, that is, the specified properties of the query object and the field values of the edited object, I would like to control whether the fields / inlines are visible to the user. I ended up doing this by adding a method can_view_field()to ModelAdmin and changing the built-in methods get_form()and get_fieldset()to remove / exclude fields + rows that the user does not have permissions (as defined can_view_field()). see. If you want to see the code, I put it in a pastebin , as it is long and only a few relevant.
It works great ... almost. It seems that I am facing some kind of thread safety or caching issue when the state of the ModelAdmin object is leaking from one request to another in a reproducible way.
I will illustrate the problem with a simple example. Suppose I have a model whose ModelAdmin I expanded with a field-level permission code. This model has two fields: - public_fieldwhich can be seen / edited by any employee - secret_fieldwhich can be seen and edited only by superusers
In this case, the method can_view_field()will look like this:
def can_view_field(self, request, obj, field_name):
"""
Returns boolean indicating whether the user has necessary permissions to
view the passed field.
"""
if obj is None:
return request.user.has_perm('%s.%s_%s' % (
self.opts.app_label,
action,
obj.__class__.__name__.lower()
))
else:
if field_name == "public_field":
return True
if field_name == "secret_field" and request.is_superuser:
return True
return False
1: , , , public_field, secret_field. ( ), public_field.
2: , , public_field. , , secret_field. 100% .
:
get_form() ModelForm. , . ModelForm .- ModelAdmin. 1 . 2 .
. ( , , ). , , ModelAdmin ? ? factory deepcopy() ModelAdmin, ModelAdmin ? . !