The default “delete selected” admin action in Django

后端 未结 8 1618
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-14 09:24

How can I remove or change the verbose name of the default admin action \"delete selected X item\" in the Django admin panel?

相关标签:
8条回答
  • 2020-12-14 10:08

    In order to replace delete_selected I do the following:

    Copy the function delete_selected from contrib/admin/actions.py to your admin.py and rename it. Also copy the template contrib/admin/templates/delete_selected_confirmation.html to your template directory and rename it. Mine looks like this:

    def reservation_bulk_delete(modeladmin, request, queryset):
        """
        Default action which deletes the selected objects.
        This action first displays a confirmation page whichs shows all the
        deleteable objects, or, if the user has no permission one of the related
        childs (foreignkeys), a "permission denied" message.
    
        Next, it delets all selected objects and redirects back to the change list.
        """
        opts = modeladmin.model._meta
        app_label = opts.app_label
    
        # Check that the user has delete permission for the actual model
        if not modeladmin.has_delete_permission(request):
            raise PermissionDenied
    
        # Populate deletable_objects, a data structure of all related objects that
        # will also be deleted.
    
        # deletable_objects must be a list if we want to use '|unordered_list' in the template
        deletable_objects = []
        perms_needed = set()
        i = 0
        for obj in queryset:
            deletable_objects.append([mark_safe(u'%s: <a href="%s/">%s</a>' % (escape(force_unicode(capfirst(opts.verbose_name))), obj.pk, escape(obj))), []])
            get_deleted_objects(deletable_objects[i], perms_needed, request.user, obj, opts, 1, modeladmin.admin_site, levels_to_root=2)
            i=i+1
    
        # The user has already confirmed the deletion.
        # Do the deletion and return a None to display the change list view again.
        if request.POST.get('post'):
            if perms_needed:
                raise PermissionDenied
            n = queryset.count()
            if n:
                for obj in queryset:
                    obj_display = force_unicode(obj)
    
                    obj.delete()
    
                    modeladmin.log_deletion(request, obj, obj_display)
                #queryset.delete()
                modeladmin.message_user(request, _("Successfully deleted %(count)d %(items)s.") % {
                    "count": n, "items": model_ngettext(modeladmin.opts, n)
                })
            # Return None to display the change list page again.
            return None
    
        context = {
            "title": _("Are you sure?"),
            "object_name": force_unicode(opts.verbose_name),
            "deletable_objects": deletable_objects,
            'queryset': queryset,
            "perms_lacking": perms_needed,
            "opts": opts,
            "root_path": modeladmin.admin_site.root_path,
            "app_label": app_label,
            'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME,
        }
    
        # Display the confirmation page
        return render_to_response(modeladmin.delete_confirmation_template or [
            "admin/%s/%s/reservation_bulk_delete_confirmation.html" % (app_label, opts.object_name.lower()),
            "admin/%s/reservation_bulk_delete_confirmation.html" % app_label,
            "admin/reservation_bulk_delete_confirmation.html"
        ], context, context_instance=template.RequestContext(request))
    

    As you can see I commented out

    queryset.delete()
    

    and rather use:

    obj.delete()
    

    That's not optimal yet - you should apply something to the entire queryset for better performance.

    In admin.py I disable the default action delete_selected for the entire admin site:

    admin.site.disable_action('delete_selected')
    

    Instead I use my own function where needed:

    class ReservationAdmin(admin.ModelAdmin):
        actions = [reservation_bulk_delete, ]
    

    In my model I define the delete() function:

    class Reservation(models.Model):
        def delete(self):
            self.status_server = RESERVATION_STATUS_DELETED
            self.save()
    
    0 讨论(0)
  • 2020-12-14 10:13

    For globally changing delete_selected's short_description Dominic Rodger's answer seems best.

    However for changing the short_description on the admin for a single model I think this alternative to Stéphane's answer is better:

    def get_actions(self, request):
        actions = super(MyModelAdmin, self).get_actions(request)
        actions['delete_selected'][0].short_description = "Delete Selected"
        return actions
    
    0 讨论(0)
提交回复
热议问题