Переопределить метод удаления модели django для массового удаления
Я переопределяю метод удаления модели Django, чтобы удалить сиротские файлы на диске для полей изображений, что-то вроде этого:
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)
это отлично работает, когда я удаляю отдельные объекты из администратора, но когда я выбираю несколько объектов и удаляю их, это, похоже, не вызывается. Я некоторое время гуглил, но не попал в правильные ключевые слова, чтобы получить ответ на этот вопрос, и официальная документация, похоже, говорит об этой теме.
2 ответов
это:
метод delete () выполняет массовое удаление и не вызывает никаких методов delete () на ваших моделях. Однако он выдает сигналы pre_delete и post_delete для всех удаленных объектов (включая каскадные удаления).
для этого вы можете переопределить метод delete на QuerySet
, а затем применить эти QuerySet
менеджер:
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)
Delete метод queryset работает непосредственно на базе данных. Он не зовет Model.delete()
методы. От docs:
имейте в виду, что это, когда это возможно, будет выполняться исключительно в SQL, и поэтому методы delete() отдельных экземпляров объектов не обязательно будут вызываться во время процесса. Если вы предоставили пользовательский метод delete () для класса модели и хотите убедиться, что он вызван, вам нужно будет "вручную" удалить экземпляры этого модель (например, путем итерации по QuerySet и вызова delete () для каждого объекта по отдельности), а не с помощью метода bulk delete () QuerySet.
если вы хотите переопределить поведение интерфейса администрирования Django по умолчанию, вы можете написать пользовательский delete
действие:
https://docs.djangoproject.com/en/1.7/ref/contrib/admin/actions/
другой метод-переопределить post_delete
(или pre_delete
) сигнала вместо delete
метод:
https://docs.djangoproject.com/en/1.7/ref/signals/#django.db.models.signals.post_delete
как pre_delete, но отправлено в конце метода delete () модели и метод delete() queryset.