Django管理员:覆盖删除方法
我的admin.py如下所示:Django管理员:覆盖删除方法,django,django-admin,Django,Django Admin,我的admin.py如下所示: class profilesAdmin(admin.ModelAdmin): list_display = ["type","username","domain_name"] 现在,我想在删除对象之前执行一些操作: class profilesAdmin(admin.ModelAdmin): list_display = ["type","username","domain_name"] @receiver(pre_del
class profilesAdmin(admin.ModelAdmin):
list_display = ["type","username","domain_name"]
现在,我想在删除对象之前执行一些操作:
class profilesAdmin(admin.ModelAdmin):
list_display = ["type","username","domain_name"]
@receiver(pre_delete, sender=profile)
def _profile_delete(sender, instance, **kwargs):
filename=object.profile_name+".xml"
os.remove(os.path.join(object.type,filename))
如果我使用像这样的删除信号方法,我会得到一个错误,说self
应该是第一个参数
如何修改上述功能?我想检索被删除对象的配置文件名称。如何做到这一点 我还尝试重写delete_model方法:
def delete_model(self, request, object):
filename=object.profile_name+".xml"
os.remove(os.path.join(object.type,filename))
object.delete()
但是,如果必须一次删除多个对象,则此方法不起作用。您使用的
delete\u model
方法是正确的。当django管理员一次对多个对象执行操作时,它使用。但是,正如您在文档中看到的,这些操作仅在数据库级别使用SQL执行
您需要将delete_model
方法添加到django admin中
def delete_model(modeladmin, request, queryset):
for obj in queryset:
filename=obj.profile_name+".xml"
os.remove(os.path.join(obj.type,filename))
obj.delete()
然后将函数添加到modeladmin中-
class profilesAdmin(admin.ModelAdmin):
list_display = ["type","username","domain_name"]
actions = [delete_model]
你的方法应该是
class profilesAdmin(admin.ModelAdmin):
#...
def _profile_delete(self, sender, instance, **kwargs):
# do something
def delete_model(self, request, object):
# do something
您应该在每个方法签名(通常称为
self
)中添加对当前对象的引用作为第一个参数。此外,delete_模型应该作为一种方法来实现。主要问题是Django管理员的批量删除使用SQL,而不是instance.delete(),如其他地方所述。对于仅限管理员的解决方案,以下解决方案保留Django管理员的“do you real want delete this”(是否真的要删除这些)间隙
最通用的解决方案是覆盖模型管理器返回的queryset以拦截delete
from django.contrib.admin.actions import delete_selected
class BulkDeleteMixin(object):
class SafeDeleteQuerysetWrapper(object):
def __init__(self, wrapped_queryset):
self.wrapped_queryset = wrapped_queryset
def _safe_delete(self):
for obj in self.wrapped_queryset:
obj.delete()
def __getattr__(self, attr):
if attr == 'delete':
return self._safe_delete
else:
return getattr(self.wrapped_queryset, attr)
def __iter__(self):
for obj in self.wrapped_queryset:
yield obj
def __getitem__(self, index):
return self.wrapped_queryset[index]
def __len__(self):
return len(self.wrapped_queryset)
def get_actions(self, request):
actions = super(BulkDeleteMixin, self).get_actions(request)
actions['delete_selected'] = (BulkDeleteMixin.action_safe_bulk_delete, 'delete_selected', ugettext_lazy("Delete selected %(verbose_name_plural)s"))
return actions
def action_safe_bulk_delete(self, request, queryset):
wrapped_queryset = BulkDeleteMixin.SafeDeleteQuerysetWrapper(queryset)
return delete_selected(self, request, wrapped_queryset)
class SomeAdmin(BulkDeleteMixin, admin.ModelAdmin):
...
您尝试重写delete_model方法失败,因为当您删除多个对象时,django使用
QuerySet.delete()
,出于效率原因,您的模型的delete()
方法将不会被调用
你可以在那里看到它注意开始警告 Admin
delete\u model()
与模型的delete()
因此,当您删除多个对象时,将永远不会调用自定义的delete方法
你有两条路
1.自定义删除操作。为每个选定项调用Model.delete()操作 2.使用信号。
您可以单独使用信号,而不是在类内部 您还可以观看此问题您可以使用从开始的用于批量删除对象,使用用于单个删除。这两种方法都将在删除对象之前处理某些内容 ModelAdmin.delete_queryset(请求,queryset)
这是关于in of的解释 delete_queryset()方法提供了HttpRequest和要删除的对象的queryset。重写此方法以自定义“删除选定对象”的删除过程 让我们看看它的作用,您可以覆盖admin。通过包含函数以这种方式初始化。在这里,您将获得对象列表,
queryset.delete()
mean一次删除所有对象,或者您可以添加一个循环来逐个删除
def delete_queryset(self, request, queryset):
print('==========================delete_queryset==========================')
print(queryset)
"""
you can do anything here BEFORE deleting the object(s)
"""
queryset.delete()
"""
you can do anything here AFTER deleting the object(s)
"""
print('==========================delete_queryset==========================')
所以我要从“选择窗口”中删除5个对象,这是这5个对象
然后你会像这样重定向到确认页面
记住“是的,我确定”按钮,我稍后会解释。当您单击该按钮时,您将在删除这5个对象后看到下图
这是终端输出
因此,您将以QuerySet列表的形式获取这5个对象,在删除之前,您可以在注释区域中执行任何您想要的操作
ModelAdmin.delete_模型(请求,obj)
这是关于的解释 HttpRequest和一个模型实例给出了delete_模型方法。重写此方法允许执行删除前或删除后操作。调用super().delete_model()以使用model.delete()删除对象 让我们看看它的作用,您可以覆盖admin。通过包含函数以这种方式初始化
actions = ['delete_model']
def delete_model(self, request, obj):
print('============================delete_model============================')
print(obj)
"""
you can do anything here BEFORE deleting the object
"""
obj.delete()
"""
you can do anything here AFTER deleting the object
"""
print('============================delete_model============================')
我只需单击我的第6个对象即可从“更改窗口”中删除
还有一个删除按钮,当你点击它时,你会看到我们之前看到的窗口
单击“是,我确定”按钮删除单个对象。您将看到以下窗口,其中包含已删除对象的通知
这是终端输出
因此,您将以单个QuerySet的形式获取选定对象,在删除之前,您可以在注释区域中执行任何您想要的操作
最后的结论是,您可以通过使用和在Django管理站点的“选择窗口”或“更改窗口”中单击“是,我确定”按钮来处理删除事件。这样我们就不需要处理像或这样的信号 这是完整的代码
from django.contrib import admin
from . import models
class AdminInfo(admin.ModelAdmin):
model = models.AdminInfo
actions = ['delete_model']
def delete_queryset(self, request, queryset):
print('========================delete_queryset========================')
print(queryset)
"""
you can do anything here BEFORE deleting the object(s)
"""
queryset.delete()
"""
you can do anything here AFTER deleting the object(s)
"""
print('========================delete_queryset========================')
def delete_model(self, request, obj):
print('==========================delete_model==========================')
print(obj)
"""
you can do anything here BEFORE deleting the object
"""
obj.delete()
"""
you can do anything here AFTER deleting the object
"""
print('==========================delete_model==========================')
admin.site.register(models.AdminInfo, AdminInfo)
但我还是得到了错误自我没有定义不,那是不可能的。如果我添加self,我会得到一个错误_profile_delete接受3个参数(给定2个),如果只删除一个对象,则会抛出一个错误。给出错误“U配置文件”对象不可编辑。此外,“操作”列表将有2个值。一个是delete_model,另一个是delete selected profiles。是的,您需要一个函数用于modeladmin操作,另一个用于单个对象(我认为您已经有了该函数)。在操作列表中有两个操作有问题吗?是的,所以我写了一个函数从列表中删除额外的操作。所以它现在可以正常工作了。Thanx
delete\u model
覆盖单个对象的删除操作,对于查询集,必须覆盖delete\u queryset
您的回答确实帮助了我..谢谢delete\u queryset
工作!谢谢@user578386欢迎您!不客气@guilhermia@KushanGunasekera,我想在根据某些条件删除对象之前引发异常并显示一些错误消息。如果我这样做,我会收到两条消息:我的错误消息+对象删除成功。你能帮我怎么做吗?