Django Admin - 如何防止删除某些内联项

8 投票
5 回答
5077 浏览
提问于 2025-04-17 13:22

我有两个模型,比如说,书籍(Book)和页面(Page)。

页面有一个外键指向书籍,也就是说每一页都和一本书关联。

每一页可以被标记为“已阅读”(was_read),我想在后台管理中防止删除那些已经被阅读的页面。

在后台管理中,页面是书籍的一个子项(inline),我不想让页面在后台成为一个独立的模型。

我的问题是,怎么才能实现已经阅读的页面不能被删除呢?我现在使用的是Django 1.4,尝试了几种方法:

  1. 重写“删除”功能,让它抛出一个验证错误(ValidationError)——问题是后台管理并不会处理这个验证错误,结果你会看到一个错误页面,所以这不是个好办法。
  2. 在PageAdminInline中重写方法——has_delete_permission,问题是这个方法是针对每种类型的,所以要么我允许删除所有页面,要么就不允许。

有没有其他好的方法,不需要重写HTML代码呢?

谢谢,
Li

5 个回答

3

你可以通过创建自己的自定义表单集来在界面上禁用删除复选框,并在其中将 can_delete 设置为 False。比如:

from django.forms import models 
from django.contrib import admin 

class MyInline(models.BaseInlineFormSet): 
    def __init__(self, *args, **kwargs): 
        super(MyInline, self).__init__(*args, **kwargs) 
        self.can_delete = False 

class InlineOptions(admin.StackedInline): 
    model = InlineModel 
    formset = MyInline 

class MainOptions(admin.ModelAdmin): 
    model = MainModel 
    inlines = [InlineOptions]
8

在你的代码中,你可以添加一个标志 can_delete=False

比如:

class MyInline(admin.TabularInline):
    model = models.mymodel
    can_delete = False
12

解决方案如下(不需要任何HTML代码):

在管理文件中,定义以下内容:

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

撰写回答