2013-03-04 9 views
11

I admin.py haben wie folgt:Django Admin: Überschreibung löschen Methode

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

Jetzt will ich eine Aktion durchführen, bevor das Objekt zu löschen:

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

Wenn i-Signal verwenden Methode löschen wie Dies bekomme ich eine Fehlermeldung self sollte der erste Parameter sein.

Wie kann ich die obige Funktion ändern?
Und ich möchte den profile_name des Objekts gelöscht werden. Wie kann das gemacht werden?

Ich habe auch versucht zwingende delete_model Methode:

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

Aber diese dosn't Arbeit, wenn mehrere Objekte auf einen Schuß gelöscht werden müssen.

+0

Noch habe ich den Fehler selbst nicht – arjun

Antwort

5

Sie sind mit Ihrer delete_model Methode auf dem richtigen Weg. Wenn der Django-Administrator eine Aktion für mehrere Objekte auf einmal ausführt, verwendet er update function. Wie Sie jedoch in den Dokumenten sehen, werden diese Aktionen nur mit SQL auf Datenbankebene ausgeführt.

Sie müssen Ihre delete_model Methode als custom action im Django-Admin hinzufügen.

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

Dann ist Ihre Funktion, um Ihre Modeladmin hinzufügen -

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

definiert Was make_published ist? – arjun

+0

Whoops, kopieren und einfügen Fehler - Ich habe meine Antwort aktualisiert. –

+0

Dies wirft einen Fehler auf, wenn nur ein Objekt gelöscht werden soll. Gibt an, dass das Objekt 'error'_profile' nicht iterierbar ist. Auch die Aktionsliste hat 2 Werte. Einer ist delete_model und der andere löscht ausgewählte Profile. – arjun

0

Ihre Methode

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

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

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

sollten Sie sollten einen Verweis auf aktuelles Objekt als erstes Argument in jeder Methode Signatur hinzufügen (normalerweise self genannt). Außerdem sollte das delete_model als Methode implementiert werden.

+0

Nein, das ist nicht möglich. Wenn ich selbst addiere, bekomme ich den Fehler _profile_delete benötigt 3 Argumente (2 gegeben) – arjun

4

Das Hauptproblem ist, dass das Massenlöschung des Django-Administrators SQL verwendet, nicht instance.delete(), wie an anderer Stelle erwähnt. Bei einer Nur-Administrator-Lösung behält die folgende Lösung den Django-Administrator bei: "Möchten Sie diese Interstitial-Einträge wirklich löschen?"

Die allgemeinste Lösung besteht darin, das vom Manager des Modells zurückgegebene Abfrage-Set zu überschreiben, um delete abzufangen.

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

Sie delete_model Methode versuchen überschrieben ist fehlgeschlagen, weil, wenn Sie mehrere Objekte die django verwenden löschen QuerySet.delete() aus Effizienzgründen Ihre delete() Methode des Modells wird nicht aufgerufen werden.

können Sie es sehen dort https://docs.djangoproject.com/en/1.9/ref/contrib/admin/actions/
den Anfang Warnung zu sehen ist

Admin delete_model() gleiche wie die delete() Modell https://github.com/django/django/blob/master/django/contrib/admin/options.py#L1005

so, wenn Sie mehrere Objekte löschen, Sie benutzerdefinierte die Löschmethode wird nie Anruf sein .

haben Sie zwei Wege.

1. benutzerdefinierte Aktion löschen.
Aktion, die Model.delete() für jedes der ausgewählten Elemente aufruft.

2.Nutzsignal.
können Sie Signal allein verwenden, nicht innerhalb der Klasse.

Sie können auch diese Frage sehen Django model: delete() not triggered

Verwandte Themen