2009-10-14 178 views

回答

12

不知道这种猴子打补丁是个好主意,但在我admin.py作品之一搡这对我来说:

from django.contrib.admin.actions import delete_selected 
delete_selected.short_description = u'How\'s this for a name?' 

这将改变冗长的名称所有您的管理网站。如果你想改变它只为一个特定模型的管理员,我认为你需要写一个custom admin action

测试和Django 1.1版:

>>> import django 
>>> django.VERSION 
(1, 1, 0, 'beta', 1) 
+0

似乎是一个聪明的方式对我来说不工作。它只是删除操作框。 – Hellnar 2009-10-14 12:23:34

+1

呵呵。我用Django 1.1测试它,它工作正常。我把它放在我的admin.py的顶部(在其他导入语句下面)。 – 2009-10-14 12:34:34

+0

对我来说它是(1,1,0,'final',0),也许就是这个原因:( – Hellnar 2009-10-14 12:37:30

19

您可以使用此代码出现禁用操作。

from django.contrib import admin 
admin.site.disable_action('delete_selected') 

如果你选择了,然后你可以在个别车型有此还原:

class FooAdmin(admin.ModelAdmin): 
    actions = ['my_action', 'my_other_action', admin.actions.delete_selected] 
+0

这太棒了 - 效果很好。 – Mark 2014-05-06 07:57:24

+0

还使用'delete_selected'而不是admin.actions.delete_selected在Django 1.6中正常工作。 – 2014-10-01 15:58:04

4

以取代delete_selected我做到以下几点:从contrib/admin/actions.py

复制功能delete_selected到您的admin.py并重命名它。同时将模板contrib/admin/templates/delete_selected_confirmation.html复制到您的模板目录并重新命名。我的是这样:

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)) 

正如你可以看到我注释掉

queryset.delete() 

,并愿意使用:

obj.delete() 

这不是最佳,但 - 你应该申请一些东西到整个查询集获得更好的性能。

在admin.py我禁用delete_selected整个管理站点的默认操作:

admin.site.disable_action('delete_selected') 

相反,我用我自己的功能,在需要的地方:

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

在我的模型我定义delete()功能:

class Reservation(models.Model): 
    def delete(self): 
     self.status_server = RESERVATION_STATUS_DELETED 
     self.save() 
23

除了Googol的解决方案,并通过等待delete_model()到be implemented in current Django version,我建议下面的代码。

它仅禁用当前AdminForm的默认删除操作。

class FlowAdmin(admin.ModelAdmin): 
    actions = ['delete_model'] 

    def get_actions(self, request): 
     actions = super(MyModelAdmin, self).get_actions(request) 
     del actions['delete_selected'] 
     return actions 

    def delete_model(self, request, obj): 
     for o in obj.all(): 
      o.delete() 
    delete_model.short_description = 'Delete flow' 

admin.site.register(Flow, FlowAdmin) 
+1

不应使用'delete_model',因为从管理员删除一个实例时使用此方法。在这种情况下,queryset参数不是查询集,它是单个实例,并且会导致循环崩溃。 – jul 2012-07-12 18:49:08

+0

这个应该被选为接受的答案。 – 2014-02-15 14:09:09

+0

我正在使用django 1.4.16和'delete_model'似乎在这两种情况下工作(没有例外或循环)。 – Paolo 2014-12-22 13:08:16

3

对于全球变化delete_selected的SHORT_DESCRIPTION Dominic Rodgeranswer似乎最好。

然而,对于改变SHORT_DESCRIPTION上管理员的单一模式,我认为这个替代Stéphaneanswer更好:

def get_actions(self, request): 
    actions = super(MyModelAdmin, self).get_actions(request) 
    actions['delete_selected'][0].short_description = "Delete Selected" 
    return actions 
0
from django.contrib.admin import sites 
from django.contrib.admin.actions import delete_selected 


class AdminSite(sites.AdminSite): 
    """ 
    Represents the administration, where only authorized users have access. 
    """ 
    def __init__(self, *args, **kwargs): 
     super(AdminSite, self).__init__(*args, **kwargs) 
     self.disable_action('delete_selected') 
     self.add_action(self._delete_selected, 'delete_selected') 

    @staticmethod 
    def _delete_selected(modeladmin, request, queryset): 
     _delete_qs = queryset.delete 

     def delete(): 
      for obj in queryset: 
       modeladmin.delete_model(request, obj) 
      _delete_qs() 

     queryset.delete = delete 
     return delete_selected(modeladmin, request, queryset) 
0
class FooAdmin(sites.AdminSite): 
     not_deleted = ['value1', 'value2'] 
     actions = ['delete_selected_values'] 

    def delete_selected_values(self, request, queryset): 
     # my custom logic 
     exist = queryset.filter(value__in=self.not_deleted).exists() 
     if exist: 
      error_message = "Error" 
      self.message_user(request, error_message, level=messages.ERROR) 
     else: 
      delete_action = super().get_action('delete_selected')[0] 
      return delete_action(self, request, queryset) 
    delete_selected_values.short_description = 'delete selected' 

admin.site.register(Foo, FooAdmin) 
+1

欢迎来到StackOverflow!请评论你的代码 – tutankhamun 2016-02-10 08:52:15