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

时间:2013-01-22 20:57:21

标签: python django django-models django-admin

我有2个模型 - 例如,Book和Page。 页面有Book的外键。

每个页面都可以标记为“was_read”(布尔值),我想阻止删除已读取的页面(在管理员中)。

在admin中 - Page是Book中的内联(我不希望Page成为管理员中的独立模型)。

我的问题 - 如何才能实现不会删除已读取的页面的行为? 我正在使用Django 1.4,我尝试了几种选择:

  1. 覆盖“删除”以抛出ValidationError - 问题是管理员在删除时没有“捕获”ValidationError而你得到一个错误页面,所以这不是一个好的选择。
  2. 在PageAdminInline中覆盖方法 - has_delete_permission - 这里的问题 - 每个类型的问题所以我允许删除所有页面,或者我不允许删除所有页面。
  3. 在没有覆盖HTML代码的情况下还有其他好的选择吗?

    谢谢, 李

4 个答案:

答案 0 :(得分:5)

解决方案如下(不需要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

答案 1 :(得分:2)

另一种技术是禁用DELETE复选框。 该解决方案的优点是可以向用户提供视觉反馈,因为她会看到一个灰色复选框。

from django.forms.models import BaseInlineFormSet

class MyInlineFormSet(BaseInlineFormSet):

    def add_fields(self, form, index):
        super().add_fields(form, index)
        if some_criteria_to_prevent_deletion:
            form.fields['DELETE'].disabled = True

此代码利用了Django 1.9中添加的Field.disabled属性。正如文档所述,“即使用户篡改了提交给服务器的字段的值,它也会被表单的初始数据中的值所忽略,因此将被忽略”,因此您无需添加更多代码来防止删除。

答案 2 :(得分:1)

我找到了一个非常简单的解决方案,可以安静地避免不必要的删除某些内联。您可以覆盖delete_forms属性方法。 这不仅适用于管理员,也适用于常规内联。

from django.forms.models import BaseInlineFormSet

class MyInlineFormSet(BaseInlineFormSet):

    @property
    def deleted_forms(self):
        deleted_forms = super(MyInlineFormSet, self).deleted_forms

        for i, form in enumerate(deleted_forms):
            # Use form.instance to access object instance if needed
            if some_criteria_to_prevent_deletion:
                deleted_forms.pop(i)

        return deleted_forms

答案 3 :(得分:1)

您可以通过创建自己的自定义来禁用删除复选框UI 内联模型的formset,并在那里设置can_deleteFalse。对于 例如:

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]