1

In my models I have Document model with foreign key to the Library model. When I am in Django admin site I want to disable editing and deleting Library instances when I am creating new Document.

Admin site, view for adding new Document

What I tried was to remove delete and edit permissions by subclassing django.contrib.admin.ModelAdmin and removing change/delete permissions

@admin.register(Library)
class LibraryAdmin(admin.ModelAdmin):
    def has_delete_permission(self, request, obj=None):
        return False

    def has_change_permission(self, request, obj=None):
        return False

This makes unwanted buttons disappear but also entirely blocks possibility of editing and removing Libraries, which is not what I want. Is there a way to disable these actions only in model edit form?

umat
  • 607
  • 1
  • 13
  • 25

2 Answers2

1

You could mark the request in the document admin:

def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
    request._editing_document = object_id is not None  # add attribute
    return super(DocumentAdmin, self).changeform_view(request, object_id=object_id, form_url=form_url, extra_context=extra_context)

Now you can access that flag in the related admin:

@admin.register(Library)
class LibraryAdmin(admin.ModelAdmin):
    def has_delete_permission(self, request, obj=None):
        if getattr(request, '_editing_document', False):  # query attribute
            return False
        return super(LibraryAdmin, self).has_delete_permission(request, obj=obj)
user2390182
  • 72,016
  • 6
  • 67
  • 89
  • Wow, this is so cool :) Thank you. It works as I want both views for creating and changing document. I wonder if I should do the same in ``add_view`` method in Document admin. – umat Jul 25 '18 at 09:35
  • 2
    `add_view` (create) and `change_view` (edit) just call `changeform_view` with slightly different params. That's why I put it there. But the general principle, of course, can be applied elsewhere. – user2390182 Jul 25 '18 at 09:51
1

Another variation, similar to that of schwobaseggl, would be:

@admin.register(Library)
class LibraryAdmin(admin.ModelAdmin):
    def has_delete_permission(self, request, obj=None):
        r = super(LibraryAdmin, self).has_delete_permission(request,obj)
        if r:
            referer = request.path
            
            # Here we can check all the forms were we don`t want to allow Library deletion
            if 'documentappname/document/' in referer:
                r = False
        
        return r

Pros: you only have to make a function, where you can avoid deleting in many editting pages for different models.
Cons: it relies on the url pattern of your admin app, so, if it changes app or model name (strange but possible) you would have to change it. Another con is that is less fine-grained: you cannot choose to avoid deletion based on some property of the object to be deleted. You coud do this with schwobaseggl's proposal.

Anr
  • 332
  • 3
  • 6