2013-03-04 146 views
11

我admin.py如下:Django管理:覆盖删除方法

class profilesAdmin(admin.ModelAdmin): 
    list_display = ["type","username","domain_name"] 

现在我想执行一些动作删除对象之前:

class profilesAdmin(admin.ModelAdmin): 
    list_display = ["type","username","domain_name"] 

    @receiver(pre_delete, sender=profile) 
    def _profile_delete(sender, instance, **kwargs): 
     filename=object.profile_name+".xml" 
     os.remove(os.path.join(object.type,filename)) 

如果我使用删除信号方法一样这我得到一个错误,说self应该是第一个参数。

如何修改上述功能?
而我想检索被删除对象的profile_name。如何才能做到这一点?

我也试着重写delete_model方法:

def delete_model(self, request, object): 
    filename=object.profile_name+".xml" 
    os.remove(os.path.join(object.type,filename)) 
    object.delete() 

但这不到风度的工作,如果多个对象必须在一个镜头被删除。

+0

不过我得到未定义 – arjun 2013-03-04 07:26:34

回答

5

您的delete_model方法处于正确的轨道上。当django管理员一次对多个对象执行操作时,它使用update function。但是,正如您在文档中看到的,这些操作仅在数据库级别使用SQL执行。

您需要在django admin中将delete_model方法添加为custom action

def delete_model(modeladmin, request, queryset): 
    for obj in queryset: 
     filename=obj.profile_name+".xml" 
     os.remove(os.path.join(obj.type,filename)) 
     obj.delete() 

那么你的功能添加到您的ModelAdmin -

class profilesAdmin(admin.ModelAdmin): 
    list_display = ["type","username","domain_name"] 
    actions = [delete_model] 
+0

什么make_published错误的自我? – arjun 2013-03-04 07:51:00

+0

哎呀,复制并粘贴错误 - 我已经更新了我的答案。 – 2013-03-04 07:55:15

+0

如果只删除一个对象,则会引发错误。给出错误'_profile'对象不可迭代。动作列表也会有2个值。一个是delete_model,另一个是删除选定的配置文件。 – arjun 2013-03-04 08:10:36

0

你的方法应该是

class profilesAdmin(admin.ModelAdmin): 
    #... 

    def _profile_delete(self, sender, instance, **kwargs): 
     # do something 

    def delete_model(self, request, object): 
     # do something 

你应该参考当前的对象添加在每个方法签名的第一个参数(通常称为self)。而且,delete_model应该作为一个方法来实现。

+0

不,这是不可能的。如果我添加自己,我得到错误_profile_delete需要3个参数(给出2) – arjun 2013-03-04 07:55:02

4

主要问题是Django管理员的批量删除使用SQL,而不是instance.delete(),如其他地方所述。对于仅限管理员的解决方案,以下解决方案保留了Django管理员的“是否真的要删除这些”插页式广告。

最常用的解决方案是重写模型管理器返回的查询集以拦截删除。

from django.contrib.admin.actions import delete_selected 

class BulkDeleteMixin(object): 
    class SafeDeleteQuerysetWrapper(object): 
     def __init__(self, wrapped_queryset): 
      self.wrapped_queryset = wrapped_queryset 

     def _safe_delete(self): 
      for obj in self.wrapped_queryset: 
       obj.delete() 

     def __getattr__(self, attr): 
      if attr == 'delete': 
       return self._safe_delete 
      else: 
       return getattr(self.wrapped_queryset, attr) 

     def __iter__(self): 
      for obj in self.wrapped_queryset: 
       yield obj 

     def __getitem__(self, index): 
      return self.wrapped_queryset[index] 

     def __len__(self): 
      return len(self.wrapped_queryset) 

    def get_actions(self, request): 
     actions = super(BulkDeleteMixin, self).get_actions(request) 
     actions['delete_selected'] = (BulkDeleteMixin.action_safe_bulk_delete, 'delete_selected', ugettext_lazy("Delete selected %(verbose_name_plural)s")) 
     return actions 

    def action_safe_bulk_delete(self, request, queryset): 
     wrapped_queryset = BulkDeleteMixin.SafeDeleteQuerysetWrapper(queryset) 
     return delete_selected(self, request, wrapped_queryset) 

class SomeAdmin(BulkDeleteMixin, admin.ModelAdmin): 
    ... 
1

您尝试重写delete_model方法失败,因为当你删除多个对象Django的使用QuerySet.delete(),为了提高效率,你的模型delete()方法不会被调用。

你可以看到它有https://docs.djangoproject.com/en/1.9/ref/contrib/admin/actions/
观看开始警告

联系delete_model()是相同型号的delete() https://github.com/django/django/blob/master/django/contrib/admin/options.py#L1005

所以当你删除多个对象,你自定义的删除方法永远不会调用。

你有两种方法。

1.自定义删除操作。
为每个选定项目调用Model.delete()。

2.使用信号。
你可以单独使用信号,而不是在课堂上。

还可以看这个问题Django model: delete() not triggered