Django Admin- disable Editing and remove “Save” buttons for a specific model

前端 未结 9 1299
眼角桃花
眼角桃花 2020-12-24 07:39

I have a Django Model which I wish to be only readonly. No adds and edits allowed.

I have marked all fields readonly and overridden has_add_permission in ModelAdmin

9条回答
  •  不知归路
    2020-12-24 08:03

    Based on the excellent answer from @mat_gessel, here's my solution:

    The main differences are UX'y:

    • use messages and redirect (with reversing-admin-urls), rather than HttpResponseForbidden to prevent a save
    • define get_readonly_fields conditionally to prevent un-saveable inputs being displayed

    Also:

    • override change_form.html app-wide, because read_only is such a useful, non-invasive enhancement
    • define has_delete_permission (may not be required by the OP)
    • test request.method != 'GET' to prevent PATCH and friends (not altogether sure if this is required, tbh)

    my_app/admin.py

    from django.core.urlresolvers import reverse
    from django.shortcuts import redirect
    
    from django.contrib import admin
    from django.contrib import messages
    
    
    class MyModelAdmin(admin.ModelAdmin):
        # let's assume two fields...
        fields = (field1, field2)
    
        def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
            if object_id:
                extra_context = extra_context or {}
                extra_context['read_only'] = True
    
                if request.method != 'GET':
                    messages.error(request, "Cannot edit a MyModel object")
                    return redirect(
                        reverse('admin:myapp_mymodel_change', args=[object_id])
                    )
    
            return super(MyModelAdmin, self).changeform_view(request, object_id, extra_context=extra_context)
    
        def has_delete_permission(self, request, obj=None):
            return False
    
        def get_readonly_fields(self, request, obj=None):
            if obj:
                # display all fields as text, rather than inputs
                return (field1, field2)
            else:
                return []
    

    admin/change_form.html

    {% extends "admin/change_form.html" %}
    {% load admin_modify %}
    {# remove the save buttons if read_only is truthy #}
    {% block submit_buttons_top %}{% if not read_only %}{% submit_row %}{% endif %}{% endblock %}
    {% block submit_buttons_bottom %}{% if not read_only %}{% submit_row %}{% endif %}{% endblock %}
    

    (Tested on Django 1.9: heads up: some imports have moved since then, eg reverse)

提交回复
热议问题