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