Revisited: Чуть более быстрое удаление объектов в админке

Итак, продолжаю переосмысливать прошлые свои советы и снипеты, которые в нынешних условиях можно реализовать более правильно и изящно.

Сейчас вот посмотрим на проблему добавления к list-view в админке своей "кнопки" с каким-то действием. Возвращаясь к старому посту про "быстрое удаление", можно придумать несколько вариантов реализации подобной концепции, но уже со свежей джангой. Вот они:

  • Для Django 1.0. Поскольку в 1.0 старая админка канула в лету, то reverse('django.contrib.admin.views.main.delete_stage') уже не работает. Но не страшно, код метода модели достаточно чуть-чуть изменить:

    def remove(self):
       from django.core.urlresolvers import reverse
       from django.contrib import admin
       return '<a href="%s" class="deletelink">Delete</a>'\
                   % reverse(admin.site.root,
                              args=("/".join([self.__class__._meta.app_label,
                                       self.__class__._meta.object_name,
                                       self.pk, 'delete']),)))
    

    Это конечно при условии, что вы используете дефолтный админский сайт (объект admin.site), иначе root надо указать объекта используемого кастомного сайта.

    Но лучше поступить по другому. Перенести этот метод в ModelAdmin класс, описывающий админку для данной модели, изменив его например так:

    class EntryAdmin(admin.ModelAdmin):
       #...
       list_display = [..., 'remove_link', ...]
       #...
    
       def remove_link(self, entry):
          from django.core.urlresolvers import reverse
          return '<a href="%s" class="deletelink">Delete</a>'\
                       % reverse(self.admin_site.root,
                                  args=("/".join([self.model._meta.app_label,
                                             self.model._meta.object_name,
                                             entry.pk, 'delete']),))
    

    При таком подходе мы получаем более переносимое решение, поскольку мы уже не зависим от какой-го конкретного админского сайта, а используем именно тот в котором зарегистрирован этот класс ModelAdmin.

  • Для Django 1.1 (и уже для текущего trunk).. Имея текущий код Джанги, и учитывая изменения, которые были внесены в логику диспетчерезации админских урлов, код можно адаптировать иначе:

     def remove_link(self, entry):
        from django.core.urlresolvers import reverse
        name = '%sadmin_%s_%s_delete' % (
             self.admin_site.name,
             self.model._meta.app_label,
             self.model._meta.module_name
        )
        return '<a href="%s" class="deletelink">Delete</a>'\
                     % reverse(name, args=(entry.pk,))
    

    В актуальной Джанге теперь админские урлы гораздо проще реверсятся, так то это можно считать рекомендуемым способом.

    Но тут версия 1.1 преподносит нам ещё одну возможность упростить работу с админкой - это групповые операции над объектами. Потрясающе удобная штука в повседневной работе, тем более что групповое удаление объектов доступно "из коробки". Хоть нашу задачу и решает косвенно, применимо к одному объекту, но вот зато когда их несколько... Я например этой штукой убиваю комментарии со спамом, которые Акисмет мне помечает - мега удобно.

Не расслабляемся и держим руку на пульсе!:-)

Комментарии 5

  1. bw написал:

    Не улавливаю, почему это ведет на удаление?

    reverse(self.adminsite.root, args=("/".join([ self.model.meta.applabel, self.model.meta.object_name, entry.pk]),))

    Может ты забыл добавить '/delete/'?

    ..bw

    Оставлен 15 Апрель 2009 в 14:30
  2. Александр Кошелев написал:

    Yep!

    Оставлен 15 Апрель 2009 в 22:50
  3. ivanff написал:

    ошибочка у вас :)

    name = '%sadmin_%s_%s_delete' % (
    

    заменить на

    name = 'admin:%s_%s_delete' % (
    
    Оставлен 28 Август 2009 в 18:09
  4. Александр Кошелев написал:

    Когда этот пост писался ещё не было неймспейсов в Джанге:-)

    Оставлен 28 Август 2009 в 18:20
  5. DavidoFF написал:

    Джанго при возврате в админскую часть заменяет символы и в игоге в коде получается что-то вроде этого:

    <a href='/admin/app/model/model_id/delete/' class='deletelink'>Delete</a>

    Оставлен 11 Декабрь 2009 в 01:03