Есть ли способ переопределить метод delete_selected в ModelAdmin, но сохранить подтверждение? - PullRequest
1 голос
/ 04 июня 2019

У меня есть:

class Person(admin.ModelAdmin):
    actions = ['delete_selected']
    def delete_selected(modeladmin, request, queryset):
        # Show confirmation page.
        for obj in queryset:
            obj.custom_delete()

Этот комментарий, который я оставил там, где я борюсь.Я все еще хочу показать страницу подтверждения перед выполнением пользовательского удаления.

1 Ответ

2 голосов
/ 04 июня 2019

Краткий ответ : вы должны переопределить delete_queryset [Django-doc] , поскольку это инкапсулирует реальную логику для удаления объектов.

Вы должны не переопределить delete_selected. Это действие определено как [GitHub] :

def delete_selected(modeladmin, request, queryset):

    # ...

    # Populate deletable_objects, a data structure of all related objects that
    # will also be deleted.
    deletable_objects, model_count, perms_needed, protected = modeladmin.get_deleted_objects(queryset, request)

    # The user has already confirmed the deletion.
    # Do the deletion and return None to display the change list view again.
    if request.POST.get('post') and not protected:
        if perms_needed:
            raise PermissionDenied
        n = queryset.count()
        if n:
            for obj in queryset:
                obj_display = str(obj)
                modeladmin.log_deletion(request, obj, obj_display)
            <b>modeladmin.delete_queryset(request, queryset)</b>
            modeladmin.message_user(request, _("Successfully deleted %(count)d %(items)s.") % {
                "count": n, "items": model_ngettext(modeladmin.opts, n)
            }, messages.SUCCESS)
        # Return None to display the change list page again.
        return None

    # ...

    context = {
        # ...
    }

    request.current_app = modeladmin.admin_site.name

    # Display the confirmation page
    return TemplateResponse(request, modeladmin.delete_selected_confirmation_template or [
        "admin/%s/%s/delete_selected_confirmation.html" % (app_label, opts.model_name),
        "admin/%s/delete_selected_confirmation.html" % app_label,
        "admin/delete_selected_confirmation.html"
    ], context)


delete_selected.allowed_permissions = ('delete',)
delete_selected.short_description = gettext_lazy("Delete selected %(verbose_name_plural)s")

Ключевым моментом здесь является то, что это действие будет выполнять надлежащие проверки, но само удаление выполняется посредством вызова:

            modeladmin.delete_queryset(request, queryset)

Таким образом, вместо этого достаточно переопределить delete_queryset с помощью:

class Person<b>Admin</b>(admin.ModelAdmin):

    actions = ['delete_selected']

    def <b>delete_queryset</b>(request, queryset):
        for obj in queryset:
            obj.custom_delete()

A ModelAdmin имеет стандартную реализацию для delete_queryset [GitHub] :

class ModelAdmin(BaseModelAdmin):

    # ...

    def delete_queryset(self, request, queryset):
        """Given a queryset, delete it from the database."""
        queryset.delete()
...