The whole model is read-only

Is there a way to create a read - only model in admin django? but I mean the whole model. So, do not add, do not delete, do not change, just see objects and fields, all as read-only?

+13
django django-models django-admin readonly
Oct 27 '11 at 18:13
source share
5 answers

ModelAdmin provides a hook to get_readonly_fields () - the following is untested, my idea is to define all the fields as ModelAdmin does, without using recursion with the readonly fields themselves:

from django.contrib.admin.util import flatten_fieldsets class ReadOnlyAdmin(ModelAdmin): def get_readonly_fields(self, request, obj=None): if self.declared_fieldsets: fields = flatten_fieldsets(self.declared_fieldsets) else: form = self.get_formset(request, obj).form fields = form.base_fields.keys() return fields 

then the subclass / mixin of this administrator, if he is to be a read-only administrator.

To add / remove, and so that their buttons disappear, you probably also want to add

  def has_add_permission(self, request): # Nobody is allowed to add return False def has_delete_permission(self, request, obj=None): # Nobody is allowed to delete return False 

PS: In ModelAdmin, if has_change_permission (lookup or your override) returns False, you donโ€™t get into the object's change view - and the link to it will not even be shown. It would be great if this happened, and by default get_readonly_fields () checked the permission to change, and in this case set all the fields to be read-only, as indicated above. That way, non-changers could at least view the data ... given that the current admin structure assumes view = edit, as jathanism points out, this will probably require the introduction of a โ€œviewโ€ permission on top of the add / change / delete. ..

EDIT: regarding setting all read-only fields, also untested, but promising:

 readonly_fields = MyModel._meta.get_all_field_names() 

EDIT: here's another one

 if self.declared_fieldsets: return flatten_fieldsets(self.declared_fieldsets) else: return list(set( [field.name for field in self.opts.local_fields] + [field.name for field in self.opts.local_many_to_many] )) 
+11
Nov 01 '11 at 10:32
source share

You can customize your ModelAdmin classes with the readonly_fields attribute. See more details.

+2
Oct 27 '11 at 19:06
source share

As "viewing permissions" will not get into Django 1.11 , unfortunately, here is the solution that your ModelAdmin only makes by saving both model changes and adding no-op model history log entries.

 def false(*args, **kwargs): """A simple no-op function to make our changes below readable.""" return False class MyModelReadOnlyAdmin(admin.ModelAdmin): list_display = [ # list your admin listview entries here (as usual) ] readonly_fields = [ # list your read-only fields here (as usual) ] actions = None has_add_permission = false has_delete_permission = false log_change = false message_user = false save_model = false 

( NOTE: Don't be mistaken the false no-op helper with built-in false . If you don't sympathize with the helper function outside the class, move it to the class, call it no_op or something else, or override the affected attributes with the usual def s. Less DRY, but if you does not matter...)

This will:

  • delete the drop-down list of actions (with "delete") in the list view
  • prohibit adding new model entries
  • prevent deletion of existing model records
  • avoid creating journal entries in model history
  • avoid displaying "has been successfully changed" after saving
  • avoid saving changes to the database

It will not be:

  • remove or replace the two buttons "Save and continue editing" and "SAVE" (which would be nice to improve the user experience)

Note that get_all_field_names (as mentioned in the accepted answer) was removed in Django 1.10 . Tested with Django 1.10.5.

+2
Feb 24 '17 at 19:02
source share

I had a similar scenario where:

  • The user must be able to create model objects.
  • The user must be able to view a list of model objects.
  • User SHOULD'NT will be able to edit the object after its creation.

1. Override view changes

Since it is possible to override change_view() in ModelAdmin, we can use this to prevent editing instances of the model after they are created. Here is an example that I used:

 def change_view(self, request, object_id, form_url='', extra_context=None): messages.error(request, 'Sorry, but editing is NOT ALLOWED') return redirect(request.META['HTTP_REFERER']) 

2. Conditionally change the rights to edit

I also realized that docs interpret the result of ModelAdmin.has_change_permission() differently:

Should return True if obj editing is enabled, otherwise False. If obj is None, it should return True or False to indicate whether editing of objects of this type will be allowed at all (for example, False will be interpreted as meaning that the current user is not allowed to edit any object of this type).

By value, I could check if obj None , in which case I return True , otherwise I return False , and this actually allows users to view the list of changes, but will not be able to edit or view change_form after saving the model instance.

 def has_change_permission(self, request, obj = None, **kwargs): if obj is None: return True else: return False 

Although I think this can also override any MODEL_can_change permissions allowing unwanted eyes to view the list of changes?

0
Jun 11 '13 at 18:02
source share

According to my test on Django 1.8, we cannot use the following as indicated in answer No. 3, but it works on Django 1.4 :

 ## self.get_formset(request, obj) ## answer 3 needs fix. Generally, alternative codes for this issue about below section ## form = self.get_formset(request, obj).form ## ## fields = form.base_fields.keys() ## 

Maybe something like:

 #~ (A) or [f.name for f in self.model._meta.fields] #~ (B) or MyModel._meta.get_all_field_names() #~ (C) list(set([field.name for field in self.opts.local_fields] + [field.name for field in self.opts.local_many_to_many] )) 
-one
Feb 07 '16 at
source share



All Articles