I have an active Django project where the admin panel is used by the customer support team. Django lacks a view
permission because of which I have to assign the change permission to the customer support team which is slightly dangerous. I have some models for which the customer support team needs just the view access and not the change access because of security issues. Why is the view
permision missing in Django? Any workaround to this?
Here's a workaround.
Models
Simply create models with view permission by inheriting them from mixin:
class ViewPermissionsMixin(models.Model):
"""
Mixin adds view permission to model.
"""
class Meta:
abstract=True
default_permissions = ('add', 'change', 'delete', 'view')
Example model:
class ExampleModel(ViewPermissionsMixin):
name = models.CharField(max_length=255)
class Meta(ViewPermissionsMixin.Meta):
abstract = False
This will add view permission that can be assigned to certain user/group. But such permission is useless without proper admin modification.
Admins
Here is mixin for your admins:
class AdminViewMixin(admin.ModelAdmin):
def has_perm(self,user,permission):
"""
Usefull shortcut for `user.has_perm()`
"""
if user.has_perm("%s.%s_%s" % (self.model._meta.app_label,permission,self.model.__name__.lower(),)):
return True
return False
def has_module_permission(self, request): # Django 1.8
pass
def has_change_permission(self, request, obj=None):
"""
Necessary permission check to let Django show change_form for `view` permissions
"""
if request.user.is_superuser:
return True
elif self.has_perm(request.user,'change'):
return True
elif self.has_perm(request.user,'view'):
return True
return super(AdminMixin, self).has_change_permission(request, obj)
def get_readonly_fields(self, request, obj=None):
"""
Turn each model field into read-only for `viewers`
"""
all_model_fields = []
for field in self.model._meta.fields:
# TODO in Django 1.8 use ModelAdmin.get_fields()
if not field.auto_created \
and (not hasattr(field,'auto_now_add') or not field.auto_now_add) \
and (not hasattr(field,'auto_now') or not field.auto_now) \
:
all_model_fields.append(field.name)
if request.user.is_superuser:
return self.readonly_fields
elif self.has_perm(request.user,'change'):
return self.readonly_fields
elif self.has_perm(request.user,'view'):
return all_model_fields
return self.readonly_fields
def change_view(self, request, object_id, extra_context=None):
"""
Disable buttons for `viewers` in `change_view`
"""
if request.user.is_superuser:
pass
elif self.has_perm(request.user,'change'):
pass
elif self.has_perm(request.user,'view'):
extra_context = extra_context or {}
extra_context['hide_save_buttons'] = True
return super(AdminViewMixin, self).change_view(request, object_id, extra_context=extra_context)
Example admin:
@admin.register(models.ExampleModel)
class ExampleAdmin(AdminViewMixin):
list_display = ('name',)
pass
Finally just assign view
permission for specific models to any user or group in your Django Admin.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With