覆盖 django 管理员 delete_queryset 的 "short_description"
Overwrite django admin delete_queryset's "short_description"
我一直在我的应用程序中覆盖 django 的 delete_queryset(主要是为了提供自定义批量删除)。
我找不到覆盖此方法的“short_description”的方法。
对于自定义方法,您可以轻松使用 short_description 属性,例如:
class MyAdminModel(admin.ModelAdmin):
def dump_model(self, request, queryset):
pass
dump_model.short_description = "My description"
但这行不通:
class MyAdminModel(admin.ModelAdmin):
def delete_queryset(self, request, queryset):
pass
delete_queryset.short_description = "My description"
我已经尝试了标准 delete_queryset 的每个 method/attribute(在 super()
调用之后的 __init__
方法中)但没有找到任何有用的东西,尽管我可能漏掉了什么。
我也试过使用 delattr 删除标准方法(也在 __init__
中),尽管它看起来有点笨拙。它也失败了,抛出一个 AttributeError :
class MyAdminModel(admin.ModelAdmin):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
delattr(self, "delete_queryset")
终于想通了
里面涉及到 and this的一些解释。
总结一下(我不完全理解),似乎 delete_selected
是调用的操作,而 delete_queryset
是执行删除工作的真正功能.但是由于 delete_queryset
是在模型外部定义的(然后在您的应用程序中全局定义),您不能在 ModelAdmin 中对其进行子类化。
我第一次尝试做这样的事情:
class MyAdminModel(admin.ModelAdmin):
def get_actions(self, request):
actions = super().get_actions(request)
function, name, _short_description = actions['delete_selected']
short_description = "I want this custom description"
function.short_description = short_description
return actions
但是您可以很容易地看到这将全局更改描述。
所以诀窍是制作函数的深层副本并将其添加到操作中。我一直在使用这个 other answer 来完成这项工作。
所以,这最终会给出这样的结果:
from django.contrib import admin
from django.db import transaction
from .models import MyModel
import types
def copy_func(f, name=None):
'''
return a function with same code, globals, defaults, closure, and
name (or provide a new name)
'''
fn = types.FunctionType(f.__code__, f.__globals__, name or f.__name__,
f.__defaults__, f.__closure__)
# in case f was given attrs (note this dict is a shallow copy):
fn.__dict__.update(f.__dict__)
return fn
@admin.register(MyModel)
class MyAdminModel(admin.ModelAdmin):
def delete_queryset(self, request, queryset):
"""
You can there rewrite wathever you want in the original function, for
instance: here apply "delete" on each instance
"""
with transaction.atomic():
for obj in queryset:
obj.delete()
def get_actions(self, request):
actions = super().get_actions(request)
name = "delete_selected"
function, name, _short_description = actions[name]
my_custom_delete_selected = copy_func(function, name)
short_description = "Supprimer définitivement les signalements sélectionnés"
del actions[name]
actions[name] = (my_custom_delete_selected, name, short_description)
return actions
编辑:
这似乎只有在“delete_selected”函数的名称保持不变的情况下才有效。否则确认表单将 return 类似“未选择的操作”的消息而不是执行删除(该消息可能有点不同,我的 django 使用的是法语消息)。
我一直在我的应用程序中覆盖 django 的 delete_queryset(主要是为了提供自定义批量删除)。
我找不到覆盖此方法的“short_description”的方法。
对于自定义方法,您可以轻松使用 short_description 属性,例如:
class MyAdminModel(admin.ModelAdmin):
def dump_model(self, request, queryset):
pass
dump_model.short_description = "My description"
但这行不通:
class MyAdminModel(admin.ModelAdmin):
def delete_queryset(self, request, queryset):
pass
delete_queryset.short_description = "My description"
我已经尝试了标准 delete_queryset 的每个 method/attribute(在 super()
调用之后的 __init__
方法中)但没有找到任何有用的东西,尽管我可能漏掉了什么。
我也试过使用 delattr 删除标准方法(也在 __init__
中),尽管它看起来有点笨拙。它也失败了,抛出一个 AttributeError :
class MyAdminModel(admin.ModelAdmin):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
delattr(self, "delete_queryset")
终于想通了
里面涉及到
总结一下(我不完全理解),似乎 delete_selected
是调用的操作,而 delete_queryset
是执行删除工作的真正功能.但是由于 delete_queryset
是在模型外部定义的(然后在您的应用程序中全局定义),您不能在 ModelAdmin 中对其进行子类化。
我第一次尝试做这样的事情:
class MyAdminModel(admin.ModelAdmin):
def get_actions(self, request):
actions = super().get_actions(request)
function, name, _short_description = actions['delete_selected']
short_description = "I want this custom description"
function.short_description = short_description
return actions
但是您可以很容易地看到这将全局更改描述。
所以诀窍是制作函数的深层副本并将其添加到操作中。我一直在使用这个 other answer 来完成这项工作。
所以,这最终会给出这样的结果:
from django.contrib import admin
from django.db import transaction
from .models import MyModel
import types
def copy_func(f, name=None):
'''
return a function with same code, globals, defaults, closure, and
name (or provide a new name)
'''
fn = types.FunctionType(f.__code__, f.__globals__, name or f.__name__,
f.__defaults__, f.__closure__)
# in case f was given attrs (note this dict is a shallow copy):
fn.__dict__.update(f.__dict__)
return fn
@admin.register(MyModel)
class MyAdminModel(admin.ModelAdmin):
def delete_queryset(self, request, queryset):
"""
You can there rewrite wathever you want in the original function, for
instance: here apply "delete" on each instance
"""
with transaction.atomic():
for obj in queryset:
obj.delete()
def get_actions(self, request):
actions = super().get_actions(request)
name = "delete_selected"
function, name, _short_description = actions[name]
my_custom_delete_selected = copy_func(function, name)
short_description = "Supprimer définitivement les signalements sélectionnés"
del actions[name]
actions[name] = (my_custom_delete_selected, name, short_description)
return actions
编辑:
这似乎只有在“delete_selected”函数的名称保持不变的情况下才有效。否则确认表单将 return 类似“未选择的操作”的消息而不是执行删除(该消息可能有点不同,我的 django 使用的是法语消息)。