79

I've managed to disable the "Delete selected" action. Easy.

But a user can still click on an item and then there's the red Delete link at the bottom.

Peter Bengtsson
  • 7,235
  • 8
  • 44
  • 53

7 Answers7

144

Simple :)

class DeleteNotAllowedModelAdmin(admin.ModelAdmin):
    # Other stuff here
    def has_delete_permission(self, request, obj=None):
        return False
Jonathan R.
  • 1,700
  • 1
  • 12
  • 5
  • 9
    The action is still in the dropdown, but throws a forbidden 403. To clean it up you have to follow my solution. Plus do this as well. – radtek Sep 12 '14 at 16:56
  • Do you want to remove the dropdown too, in case of that, follow radtek's solution – Capuchin Sep 24 '14 at 09:33
  • 1
    @radtek You are correct, that the action will still be in the dropdown, but the OP did state that he's already managed to disable the delete selected action. So this is all that's necessary. – McKay Oct 18 '16 at 18:27
  • Thats fine, I posted the complete solution 2 years ago.. not an issue. – radtek Oct 18 '16 at 19:30
93

If you want to disable an specific one that isn't custom do this. In django 1.6.6 I had to extend get_actions plus define has_delete_permission. The has_delete_permission solution does not get rid of the action from the dropdown for me:

class MyModelAdmin(admin.ModelAdmin):

    ....

    def get_actions(self, request):
        #Disable delete
        actions = super(MyModelAdmin, self).get_actions(request)
        del actions['delete_selected']
        return actions

    def has_delete_permission(self, request, obj=None):
        #Disable delete
        return False

Not including it in actions = ['your_custom_action'], only works for the custom actions (defs) you have defined for that model. The solution AdminSite.disable_action('delete_selected'), disables it for all models, so you would have to explicitly include them later per each modelAdmin

meshy
  • 8,470
  • 9
  • 51
  • 73
radtek
  • 34,210
  • 11
  • 144
  • 111
11

Simply disable the yourapp.delete_yourmodel permission for that user or the group to which (s)he belongs.

Aidas Bendoraitis
  • 3,965
  • 1
  • 30
  • 45
  • This doesn't work in Django 1.3 and earlier versions, because of this issue https://code.djangoproject.com/ticket/8060 It's fixed in Django 1.4. – Teemu Kurppa May 30 '12 at 10:45
9

Well you probably are using:

AdminSite.disable_action('delete_selected')

For further control just implement your own admin and set its actions to whatever you need:

class MyModelAdmin(admin.ModelAdmin):
    actions = ['whatever', 'actions']

Reference: http://docs.djangoproject.com/en/dev/ref/contrib/admin/actions/#disabling-a-site-wide-action

Yuval Adam
  • 161,610
  • 92
  • 305
  • 395
5

The solutions here are already nice, but I prefer to have it as a reusable mixin, like this:

class NoDeleteAdminMixin:
    def has_delete_permission(self, request, obj=None):
        return False

You can use this in all your admins where you want to prevent deletion like this:

class MyAdmin(NoDeleteAdminMixin, ModelAdmin):
    ...
devsnd
  • 7,382
  • 3
  • 42
  • 50
3

admin.site.disable_action('delete_selected')

From the docs

JSEvgeny
  • 2,550
  • 1
  • 24
  • 38
Lucas B
  • 2,183
  • 1
  • 22
  • 22
0

This is very old, but still, it may help someone.

Assuming that OP's

... user can still click on an item and then there's the red Delete link at the bottom.

refers to the red button in the "change" view. This button can be removed by extending the ModelAdmin.change_view method as follows:

def change_view(self, request, object_id=None, form_url='', extra_context=None):
    return super().change_view(request, object_id, form_url,
                               extra_context=dict(show_delete=False))

You can do the same with show_save, and show_save_and_continue. More info and alternatives here.

Also note that, as of version 2.1, Django has a separate has_view_permission (docs), which may be a better option, depending on your use case.

djvg
  • 11,722
  • 5
  • 72
  • 103