2015-03-06 8 views
12

Ich zwingende Django Modell Methode löschen, um verwaiste Dateien auf der Disk für Bildfelder zu löschen, so etwas wie diese:Aufschalten Djangos Modellmethode für Massenlöschung löscht

class Image(models.Model): 
    img = models.ImageField(upload_to=get_image_path) 
    ... 
    def delete(self, *args, **kwargs): 
     self.img.delete() 
     super(Image, self).delete(*args, **kwargs) 

Das funktioniert gut, wenn ich lösche Single Objekte aus dem Admin, aber wenn ich mehrere Objekte auswähle und sie lösche, scheint dies nicht aufgerufen zu werden. Ich habe eine Weile gegoogelt, aber habe nicht die richtigen Stichworte gefunden, um die Antwort dafür zu bekommen, noch scheint die offizielle Dokumentation über dieses Thema zu sprechen.

Antwort

19

It does:

Die Methode delete() tut ein Bulk löschen und rufen keine delete() Methoden auf Ihre Modelle. Es gibt jedoch die Signale pre_delete und post_delete für alle gelöschten Objekte aus (einschließlich kaskadierter Löschungen).

Um das zu umgehen, können Sie auf QuerySet Löschmethode außer Kraft setzen können, und dann gilt, dass QuerySet als Trainer:

class ImageQuerySet(models.QuerySet): 

    def delete(self, *args, **kwargs): 
     for obj in self: 
      obj.img.delete() 
     super(ImageQuerySet, self).delete(*args, **kwargs) 

class Image(models.Model): 
    objects = ImageQuerySet.as_manager() 
    img = models.ImageField(upload_to=get_image_path) 
    ... 
    def delete(self, *args, **kwargs): 
     self.img.delete() 
     super(Image, self).delete(*args, **kwargs) 
+0

Ich denke, dass ich das in der Dokumentation gelesen habe, wusste aber nicht, dass es auf den Massenlöschvorgang des Administrators angewendet wurde. Wie auch immer, ich mochte deine Lösung, vielen Dank! –

6

Delete-Methode von Queryset funktioniert direkt in der Datenbank. Es ruft keine Model.delete() Methoden auf. Vom docs:

Denken Sie daran, dass dies, wenn möglich, rein in SQL ausgeführt werden, und so die delete() Methoden der einzelnen Objektinstanzen nicht notwendigerweise während des Prozesses aufgerufen werden. Wenn Sie eine benutzerdefinierte delete() -Methode für eine Modellklasse bereitgestellt haben und sicherstellen möchten, dass sie aufgerufen wird, müssen Sie Instanzen dieses Modells "manuell" löschen (z. B. durch Iterieren über ein QuerySet und Aufrufen von delete()) jedes Objekt einzeln), anstatt die Methode bulk delete() eines QuerySets zu verwenden.

Wenn Sie Django-Administrationsoberfläche Standardverhalten außer Kraft setzen möchten, können Sie eine benutzerdefinierte delete Aktion schreiben:

https://docs.djangoproject.com/en/1.7/ref/contrib/admin/actions/

Eine andere Methode ist post_delete (oder pre_delete) Signal statt delete Methode außer Kraft zu setzen:

https://docs.djangoproject.com/en/1.7/ref/signals/#django.db.models.signals.post_delete

Wie pre_delete, aber am Ende der delete() -Methode eines Modells und der delete() -Methode eines Querysets gesendet.

+1

Dank für die Lösung. Ich werde ihnen einen Versuch geben, aber ich werde GwynBleidDs Antwort als akzeptiert markieren, weil ich seinen Ansatz bevorzuge (scheint sauberer zu sein). –