我有2个模型 - 例如,Book和Page。 页面有Book的外键。
每个页面都可以标记为“was_read”(布尔值),我想阻止删除已读取的页面(在管理员中)。
在admin中 - Page是Book中的内联(我不希望Page成为管理员中的独立模型)。
我的问题 - 如何才能实现不会删除已读取的页面的行为? 我正在使用Django 1.4,我尝试了几种选择:
在没有覆盖HTML代码的情况下还有其他好的选择吗?
谢谢, 李
答案 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_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]