Readonly models in Django admin interface?

前端 未结 14 1435
北恋
北恋 2020-12-02 05:53

How can I make a model completely read-only in the admin interface? It\'s for a kind of log table, where I\'m using the admin features to search, sort, filter etc, but there

相关标签:
14条回答
  • 2020-12-02 06:14

    I have written a generic class to handle ReadOnly view depending on User permissions, including inlines ;)

    In models.py:

    class User(AbstractUser):
        ...
        def is_readonly(self):
            if self.is_superuser:
                return False
            # make readonly all users not in "admins" group
            adminGroup = Group.objects.filter(name="admins")
            if adminGroup in self.groups.all():
                return False
            return True
    

    In admin.py:

    # read-only user filter class for ModelAdmin
    class ReadOnlyAdmin(admin.ModelAdmin):
        def __init__(self, *args, **kwargs):
            # keep initial readonly_fields defined in subclass
            self._init_readonly_fields = self.readonly_fields
            # keep also inline readonly_fields
            for inline in self.inlines:
                inline._init_readonly_fields = inline.readonly_fields
            super().__init__(*args,**kwargs)
        # customize change_view to disable edition to readonly_users
        def change_view( self, request, object_id, form_url='', extra_context=None ):
            context = extra_context or {}
            # find whether it is readonly or not 
            if request.user.is_readonly():
                # put all fields in readonly_field list
                self.readonly_fields = [ field.name for field in self.model._meta.get_fields() if not field.auto_created ]
                # readonly mode fer all inlines
                for inline in self.inlines:
                    inline.readonly_fields = [field.name for field in inline.model._meta.get_fields() if not field.auto_created]
                # remove edition buttons
                self.save_on_top = False
                context['show_save'] = False
                context['show_save_and_continue'] = False
            else:
                # if not readonly user, reset initial readonly_fields
                self.readonly_fields = self._init_readonly_fields
                # same for inlines
                for inline in self.inlines:
                    inline.readonly_fields = self._init_readonly_fields
            return super().change_view(
                        request, object_id, form_url, context )
        def save_model(self, request, obj, form, change):
            # disable saving model for readonly users
            # just in case we have a malicious user...
            if request.user.is_readonly():
                # si és usuari readonly no guardem canvis
                return False
            # if not readonly user, save model
            return super().save_model( request, obj, form, change )
    

    Then, we can just inherit normally our classes in admin.py:

    class ContactAdmin(ReadOnlyAdmin):
        list_display = ("name","email","whatever")
        readonly_fields = ("updated","created")
        inlines = ( PhoneInline, ... )
    
    0 讨论(0)
  • 2020-12-02 06:15

    with django 2.2, readonly admin can be as simple as:

    class ReadOnlyAdminMixin():
        def has_add_permission(self, request):
            return False
    
        def has_change_permission(self, request, obj=None):
            return False
    
        def has_delete_permission(self, request, obj=None):
            return False
    
    
    class LogEntryAdmin(ReadOnlyAdminMixin, admin.ModelAdmin):
        list_display = ('id', 'user', 'action_flag', 'content_type', 'object_repr')
    
    0 讨论(0)
  • 2020-12-02 06:16

    read-only => views permission

    1. pipenv install django-admin-view-permission
    2. add 'admin_view_permission' to INSTALLED_APPS in the settings.py.like this: `INSTALLED_APPS = [ 'admin_view_permission',
    3. python manage.py migrate
    4. python manage.py runserver 6666

    ok.have fun with the 'views' permission

    0 讨论(0)
  • 2020-12-02 06:18

    This was added in to Django 2.1 which was released on 8/1/18!

    ModelAdmin.has_view_permission() is just like the existing has_delete_permission, has_change_permission and has_add_permission. You can read about it in the docs here

    From the release notes:

    This allows giving users read-only access to models in the admin. ModelAdmin.has_view_permission() is new. The implementation is backwards compatible in that there isn’t a need to assign the “view” permission to allow users who have the “change” permission to edit objects.

    0 讨论(0)
  • 2020-12-02 06:18

    Compiling @darklow and @josir 's excellent answers, plus adding a bit more to remove "Save" and "Save and Continue" buttons leads to (in Python 3 syntax):

    class ReadOnlyAdmin(admin.ModelAdmin):
        """Provides a read-only view of a model in Django admin."""
        readonly_fields = []
    
        def change_view(self, request, object_id, extra_context=None):
            """ customize add/edit form to remove save / save and continue """
            extra_context = extra_context or {}
            extra_context['show_save_and_continue'] = False
            extra_context['show_save'] = False
            return super().change_view(request, object_id, extra_context=extra_context)
    
        def get_actions(self, request):
            actions = super().get_actions(request)
            if 'delete_selected' in actions:
                del actions['delete_selected']
            return actions
    
        def get_readonly_fields(self, request, obj=None):
            return list(self.readonly_fields) + \
               [field.name for field in obj._meta.fields] + \
               [field.name for field in obj._meta.many_to_many]
    
        def has_add_permission(self, request):
            return False
    
        def has_delete_permission(self, request, obj=None):
            return False
    

    and then you use like

    class MyModelAdmin(ReadOnlyAdmin):
        pass
    

    I've only tried this with Django 1.11 / Python 3.

    0 讨论(0)
  • 2020-12-02 06:25

    Actually you can try this simple solution:

    class ReadOnlyModelAdmin(admin.ModelAdmin):
        actions = None
        list_display_links = None
        # more stuff here
    
        def has_add_permission(self, request):
            return False
    
    • actions = None: avoids showing the dropdown with the "Delete selected ..." option
    • list_display_links = None: avoids clicking in columns to edit that object
    • has_add_permission() returning False avoids creating new objects for that model
    0 讨论(0)
提交回复
热议问题