Skip to content

Instantly share code, notes, and snippets.

@vikalpj
Last active November 25, 2022 19:57
Show Gist options
  • Save vikalpj/63c916e982be579a49ff417d91fe8b7d to your computer and use it in GitHub Desktop.
Save vikalpj/63c916e982be579a49ff417d91fe8b7d to your computer and use it in GitHub Desktop.
@register.inclusion_tag('admin/submit_line.html', takes_context=True)
def submit_row(context):
"""
Displays the row of buttons for delete and save.
"""
ctx = original_submit_row(context)
ctx.update({
'show_save_and_add_another': context.get('show_save_and_add_another', ctx['show_save_and_add_another']),
'show_save_and_continue': context.get('show_save_and_continue', ctx['show_save_and_continue']),
'read_only': context.get('read_only', False)
})
return ctx
class ReadOnlyAdmin(admin.ModelAdmin):
"""
Mixin to be used for customizing admin for Readonly access.
1. change_view_readonly_fields - Makes fields editable in add view but readonly in edit view.
2. Makes all fields/model fields readonly and user can not change anything in edit view.
3. Hides the "Save And Add Another" & "Save And Continue" buttons.
4. Make Readonly JSON fields pretty.
TODO: Hide "Save" button as well from readonly view.
This will require Django admin template override - "admin/submit_line.html".
"""
change_view_readonly_fields = ()
def __init__(self, model, admin_site):
super(ReadOnlyAdmin, self).__init__(model, admin_site)
# Store JSON fields of the model
self._json_fields = tuple([f.name for f in self.model._meta.fields if isinstance(f, StrictJsonField)])
@property
def json_fields(self):
return self._json_fields
def user_is_readonly(self, request):
"""
This method defines the readonly access. By default all users other than superuser gets readonly access
but it can be customized at per ModelAdmin level.
"""
return not request.user.is_superuser
def get_form(self, request, obj=None, **kwargs):
form = super(ReadOnlyAdmin, self).get_form(request, obj, **kwargs)
# Remove json_fields from readonly and make them disabled instead.
json_readonly_fields = tuple(set(self._get_all_readonly_fields(request, obj)) & set(self.json_fields))
for field_name in json_readonly_fields:
if field_name in form.base_fields:
form.base_fields[field_name].widget = ReadOnlyTextAreaWidget(getattr(obj, field_name, ''))
return form
def _get_all_readonly_fields(self, request, obj=None):
readonly_fields = self.readonly_fields
if self.user_is_readonly(request):
readonly_fields = self.fields or tuple([f.name for f in self.model._meta.fields])
if obj: # editing an existing object
readonly_fields = readonly_fields + tuple(set(self.change_view_readonly_fields) - set(readonly_fields))
return readonly_fields
def get_readonly_fields(self, request, obj=None):
# Remove json_fields from readonly and make them disabled instead.
readonly_fields = tuple(set(self._get_all_readonly_fields(request, obj)) - set(self.json_fields))
return readonly_fields
def change_view(self, request, object_id, form_url='', extra_context=None):
extra_context = self.update_context(request, extra_context)
return super(ReadOnlyAdmin, self).change_view(request, object_id,
form_url, extra_context=extra_context)
def add_view(self, request, form_url='', extra_context=None):
extra_context = self.update_context(request, extra_context)
return super(ReadOnlyAdmin, self).add_view(request,
form_url, extra_context=extra_context)
def update_context(self, request, extra_context):
extra_context = extra_context or {}
extra_context['show_save_and_add_another'] = False
extra_context['show_save_and_continue'] = False
if self.user_is_readonly(request):
extra_context['read_only'] = False
return extra_context
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment