Django Admin - how to prevent deletion of some of the inlines

django, django-admin, django-models, python

Solution

The solution is as follows (no HTML code is required):

In admin file, define the following:

from django.forms.models import BaseInlineFormSet

class PageFormSet(BaseInlineFormSet):

    def clean(self):
        super(PageFormSet, self).clean()

        for form in self.forms:
            if not hasattr(form, 'cleaned_data'):
                continue                     

            data = form.cleaned_data
            curr_instance = form.instance
            was_read = curr_instance.was_read


            if (data.get('DELETE') and was_read):            
                raise ValidationError('Error')



class PageInline(admin.TabularInline):
    model = Page
    formset = PageFormSet

Problem

I have 2 models - for example, Book and Page. Page has a foreign key to Book. Each page can be marked as "was_read" (boolean), and I want to prevent deleting pages that were read (in the admin). In the admin - Page is an inline within Book (I don't want Page to be a standalone model in the admin). My problem - how can I achieve the behavior that a page that was read won't be deleted? I'm using Django 1.4 and I tried several options: - Override "delete" to throw a ValidationError - the problem is that the admin doesn't "catch" the ValidationError on delete and you get an error page, so this is not a good option. - Override in the PageAdminInline the method - has_delete_permission - the problem here -it's per type so either I allow to delete all pages or I don't. Are there any other good options without overriding the html code? Thanks, Li

Original source