如何覆盖模型上的delete()并使其仍然可以使用相关的删除

时间:2009-10-08 00:31:39

标签: python django django-models overloading

我遇到了问题,因为我正在使用some_widget_instance.delete()删除Widget。我还有一个名为WidgetFile的模型,它有一个覆盖delete()方法,这样我就可以在删除WidgetFile时删除硬盘上的文件。我遇到的问题是,如果我删除一个Widget,它的WidgetFiles就像这样:

class WidgetFile(models.Model):

    widget = models.ForeignKey(Widget)

好吧,当我删除该Widget时,它的WidgetFiles被删除但是delete()方法不会触发并执行我的额外硬盘驱动器。非常感谢任何帮助。

8 个答案:

答案 0 :(得分:63)

我正在做同样的事情,并注意到你应该考虑的Django文档中的一个金块。

Overriding predefined model methods

  

覆盖删除   请注意,使用QuerySet批量删除对象时,不一定要调用对象的delete()方法。为确保执行自定义删除逻辑,您可以使用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)

答案 1 :(得分:32)

我明白了。我只是把它放在Widget模型上:

def delete(self):
    files = WidgetFile.objects.filter(widget=self)
    if files:
        for file in files:
            file.delete()
    super(Widget, self).delete()

这会触发每个相关对象上必要的delete()方法,从而触发我的自定义文件删除代码。这是数据库更昂贵的肯定,但是当你试图删除硬盘上的文件时,再多次点击数据库并不是一笔很大的费用。

答案 2 :(得分:2)

删除前使用clear(),删除相关对象集中的所有对象。

请参阅django-following-relationships-backward

示例:

group.link_set.clear() 
group.delete() 

答案 3 :(得分:1)

如果一个Widget完全连接到一个WidgetFile,这似乎只是意义上的。在这种情况下,您应该使用OneToOneField

来自On-to-one examples:

# Delete the restaurant; the waiter should also be removed
>>> r = Restaurant.objects.get(pk=1)
>>> r.delete()

答案 4 :(得分:1)

只是想尽可能地解决这个问题:pre-delete signal。 (不以任何方式暗示没有实际的解决方案。)

答案 5 :(得分:1)

它应该像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

你忘了传递一些论点

答案 6 :(得分:0)

some_widget_instanceWidgetWidgetFile的实例?因为如果它是Widget的实例,它将无法获得delete()类中的自定义WidgetFile函数。

答案 7 :(得分:0)

从Django 1.9开始,如果您只为字段定义on_delete=models.CASCADE,它将删除删除时的所有相关对象。