6

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

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

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

我的问题 - 我怎样才能实现读取的页面不会被删除的行为?我正在使用 Django 1.4,我尝试了几个选项:

  1. 覆盖“删除”以引发 ValidationError - 问题是管理员在删除时没有“捕获” ValidationError 并且您得到一个错误页面,因此这不是一个好的选择。
  2. 在 PageAdminInline 中覆盖该方法 - has_delete_permission - 这里的问题 - 它是每个类型的,所以我允许删除所有页面,或者我不允许。

在不覆盖 html 代码的情况下,还有其他好的选择吗?

谢谢,李

4

4 回答 4

9

解决方案如下(无需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
于 2013-02-11T19:54:31.373 回答
3

您可以通过为内联模型创建自己的自定义表单集来禁用删除复选框 UI,并将其设置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]
于 2017-08-11T08:01:36.437 回答
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属性。正如文档所说,“即使用户篡改了提交给服务器的字段值,它也会被忽略,取而代之的是表单初始数据中的值”,因此您无需添加更多代码来防止删除。

于 2019-10-03T10:13:31.830 回答
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
于 2014-10-26T08:27:09.897 回答