views:

725

answers:

2

I have a model:

class MyModel(models.Model):
 ...
    def save(self):
        print "saving"
        ...
    def delete(self):
        print "deleting"
        ...

The save()-Method is triggered, but the delete() is not. I use the latest svn-Version (Django version 1.2 pre-alpha SVN-11593), and concerning the documentation at http://www.djangoproject.com/documentation/models/save%5Fdelete%5Fhooks/ this should work. Any ideas?

+6  A: 

I think you're probably using the admin's bulk delete feature, and are running into the fact that the admin's bulk delete method doesn't call delete() (see the related ticket).

I've got round this in the past by writing a custom admin action for deleting models.

If you're not using the admin's bulk delete method (e.g. you're clicking the delete button on the object's edit page) then something else is going on.

See the warning here:

The “delete selected objects” action uses QuerySet.delete() for efficiency reasons, which has an important caveat: your model’s delete() method will not be called.

If you wish to override this behavior, simply write a custom action which accomplishes deletion in your preferred manner – for example, by calling Model.delete() for each of the selected items.

For more background on bulk deletion, see the documentation on object deletion.

My custom admin model looks like this:

from photoblog.models import PhotoBlogEntry
from django.contrib import admin    

class PhotoBlogEntryAdmin(admin.ModelAdmin):
    actions=['really_delete_selected']

    def get_actions(self, request):
        actions = super(PhotoBlogEntryAdmin, self).get_actions(request)
        del actions['delete_selected']
        return actions

    def really_delete_selected(self, request, queryset):
        for obj in queryset:
            obj.delete()

        if queryset.count() == 1:
            message_bit = "1 photoblog entry was"
        else:
            message_bit = "%s photoblog entries were" % queryset.count()
        self.message_user(request, "%s successfully deleted." % message_bit)
    really_delete_selected.short_description = "Delete selected entries"

admin.site.register(PhotoBlogEntry, PhotoBlogEntryAdmin)
Dominic Rodger
yup, that's it, thanks a lot. could you shortly explain how your custom admin method looks like?
schneck
@schneck - Sure thing!
Dominic Rodger
btw - there may well be more elegant ways of accomplishing it, but it works!
Dominic Rodger
perfect - thanks!
schneck
This works great. One thing I notice is that this doesn't display the "are you sure?" page that was there previously. Any thoughts?
mikec
@mikec - go take a look at http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/actions.py - you can probably just override the bit you need (currently line 47 -`queryset.delete()`) - using something similar to the advice on extending generic views (http://www.b-list.org/weblog/2006/nov/16/django-tips-get-most-out-generic-views/) - i.e. write a method to do the initial setup and handle the post, and otherwise, just delegate to `django.contrib.admin.actions.delete_selected`. If that doesn't make sense, ask a question for more help, and ping me in this comment thread.
Dominic Rodger
A: 

hi,

if you want the intermediate confirmation page do it like that:

http://stackoverflow.com/questions/1565812/the-default-delete-selected-admin-action-in-django

cheers,

philipp

Googol