1👍
I finally figured it out.
It involves some explanations from this other question and this.
To sum it up (I don’t understand it completly), it seems that the delete_selected
is the action called and that the delete_queryset
is the real function doing the job of the deletion. But as the delete_queryset
is defined outside of the model (and then defined globally on your app), you can’t subclass it in your ModelAdmin.
I first tried to do something like this :
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
But you can easily see that this will change the description globally.
So the trick would be instead to make a deep copy of the function and add it to the actions. I have been using this other answer to do the job.
So, this would at last give something like this :
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
Edit :
This seems to work only if the name of the "delete_selected" function stays unchanged. Otherwise the confirmation form will return something like a "no chosen action" message instead of performing the deletion (the message might be a tad different, my django is using french messages).