我遇到了问题,因为我正在使用some_widget_instance.delete()删除Widget。我还有一个名为WidgetFile的模型,它有一个覆盖delete()方法,这样我就可以在删除WidgetFile时删除硬盘上的文件。我遇到的问题是,如果我删除一个Widget,它的WidgetFiles就像这样:
class WidgetFile(models.Model):
widget = models.ForeignKey(Widget)
好吧,当我删除该Widget时,它的WidgetFiles被删除但是delete()方法不会触发并执行我的额外硬盘驱动器。非常感谢任何帮助。
答案 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
# 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_instance
和Widget
或WidgetFile
的实例?因为如果它是Widget
的实例,它将无法获得delete()
类中的自定义WidgetFile
函数。
答案 7 :(得分:0)
从Django 1.9开始,如果您只为字段定义on_delete=models.CASCADE
,它将删除删除时的所有相关对象。