Nic*_*ick 12 django django-admin
假设我有一个模型,其中ID为1的行是特殊的,不应该被删除,但所有其他行都可以删除.这是我尝试实现该逻辑:
from django.db import models
class Widget(models.Model):
name = models.CharField(max_length=255)
class Meta:
ordering = ('name',)
def __unicode__(self):
return self.name
Run Code Online (Sandbox Code Playgroud)
from django.contrib import admin
from .models import Widget
class WidgetAdmin(admin.ModelAdmin):
def has_delete_permission(self, request, obj=None):
return obj is None or obj.pk != 1
admin.site.register(Widget, WidgetAdmin)
Run Code Online (Sandbox Code Playgroud)
当上面的代码去除的变化形式"删除"按钮obj.pk是1,这是我想要的.但是,在更改列表中,如果我选中ID为1的行的复选框,然后使用"删除所选小部件"操作,我可以删除该行.我想阻止它,但仍然允许使用"删除所选小部件"操作删除所有其他行.我怎样才能做到这一点?
Ant*_*ard 12
def has_delete_permission(self, request, obj=None):
"""
Returns True if the given request has permission to change the given
Django model instance, ...
"""
Run Code Online (Sandbox Code Playgroud)
这意味着has_delete_permission每个请求执行,而不是每个对象.在批量操作上,obj未设置.但是你可以检查request:
def has_delete_permission(self, request, obj=None):
if request.POST and request.POST.get('action') == 'delete_selected':
return '1' not in request.POST.getlist('_selected_action')
return obj is None or obj.pk != 1
Run Code Online (Sandbox Code Playgroud)
请注意,上述工程,因为该delete_selected动作需要has_delete_permission考虑.
您可能还想提供有关错误的一些详细信息:
from django.contrib import messages
def has_delete_permission(self, request, obj=None):
if request.POST and request.POST.get('action') == 'delete_selected':
if '1' in request.POST.getlist('_selected_action'):
messages.add_message(request, messages.ERROR, (
"Widget #1 is protected, please remove it from your selection "
"and try again."
))
return False
return True
return obj is None or obj.pk != 1
Run Code Online (Sandbox Code Playgroud)
我认为has_delete_permission出于性能原因,每个请求而不是每个对象都会调用它.在一般情况下,在运行查询之前进行SELECT查询和循环has_delete_permission(根据其工作可能是耗时的)是没用的DELETE.当与此相关时,由开发人员采取必要的步骤.
您可以delete_selected使用自己的操作替换管理员的操作实现.就像是:
from django.contrib.admin import actions
class WidgetAdmin(admin.ModelAdmin):
actions = [delete_selected]
def delete_selected(self, request, queryset):
# Handle this however you like. You could raise PermissionDenied,
# or just remove it, and / or use the messages framework...
queryset = queryset.exclude(pk=1)
actions.delete_selected(self, request, queryset)
delete_selected.short_description = "Delete stuff"
Run Code Online (Sandbox Code Playgroud)
有关详细信息,请参阅文档.