Как переопределить delete() на модели и работать с соответствующими удалениями
У меня проблема, потому что я удаляю виджет, используя some_widget_instance.delete(). У меня также есть модель под названием WidgetFile с методом override delete(), чтобы я мог удалять файлы с моего жесткого диска при удалении WidgetFile. Проблема, с которой я столкнулась, заключается в том, что если я удалю Widget, и у него есть связанные с ним WidgetFiles:
class WidgetFile(models.Model):
widget = models.ForeignKey(Widget)
Ну, когда я удаляю этот виджет, он удаляет файлы WidgetFiles, но метод delete() не запускается и не выполняет дополнительные операции с жестким диском. Любая помощь очень ценится.
Ответы
Ответ 1
Я понял это. Я просто положил это на эту модель виджетов:
def delete(self):
files = WidgetFile.objects.filter(widget=self)
if files:
for file in files:
file.delete()
super(Widget, self).delete()
Это вызвало необходимый метод delete() для каждого из связанных объектов, тем самым инициировав мой код удаления файла. Это более дешевая база данных да, но когда вы пытаетесь удалить файлы на жестком диске в любом случае, это не так уж большой расход, чтобы поразить db несколько лишних раз.
Ответ 2
Я делаю то же самое и замечаю самородок в документах Django, о которых вам следует подумать.
Переопределение предопределенных методов модели
Переопределение удаления Обратите внимание, что метод delete() для объекта не обязательно вызывается при удалении объектов в массе с помощью QuerySet. Чтобы обеспечить выполнение индивидуальной логики удаления, вы можете использовать сигналы pre_delete и/или post_delete.
Это означает, что ваш фрагмент не всегда будет делать то, что вы хотите. Использование Signals - лучший вариант для устранения удаления.
Я пошел со следующим:
import shutil
from django.db.models.signals import pre_delete
from django.dispatch import receiver
@receiver(pre_delete)
def delete_repo(sender, instance, **kwargs):
if sender == Set:
shutil.rmtree(instance.repo)
Ответ 3
Используя clear()
перед удалением, удаляет все объекты из соответствующего объекта.
см. django-follow-relationship-backward
Пример:
group.link_set.clear()
group.delete()
Ответ 4
Является ли some_widget_instance
и экземпляром Widget
или WidgetFile
? Потому что, если это экземпляр Widget
, он не получит вашу пользовательскую функцию delete()
, которая находится в классе WidgetFile
.
Ответ 5
Это похоже только на полноту, если один Widget точно связан с одним WidgetFile. В этом случае вы должны использовать OneToOneField
из Примеры "один-к-одному" :
# Delete the restaurant; the waiter should also be removed
>>> r = Restaurant.objects.get(pk=1)
>>> r.delete()
Ответ 6
Просто, чтобы бросить возможный путь вокруг этой проблемы: pre-delete signal. (Никоим образом не подразумевая, что нет никакого реального решения.)
Ответ 7
Он должен выглядеть так, как описано на django сайте:
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def save(self, *args, **kwargs):
do_something()
super(Blog, self).save(*args, **kwargs) # Call the "real" save() method.
do_something_else()
http://docs.djangoproject.com/en/dev/topics/db/models/#overriding-predefined-model-methods
вы забыли передать некоторые аргументы
Ответ 8
Из Django 1.9, если вы просто определите on_delete=models.CASCADE
для поля, он удалит все связанные объекты при удалении.