如何重写模型的delete()方法并支持相关删除
我遇到了一个问题,我通过调用 some_widget_instance.delete() 来删除一个 Widget。同时,我有一个叫 WidgetFile 的模型,它有一个重写的 delete() 方法,这样当删除 WidgetFile 时,我可以把硬盘上的文件也删除掉。问题是,当我删除一个 Widget 时,如果它有相关的 WidgetFiles,像这样:
class WidgetFile(models.Model):
widget = models.ForeignKey(Widget)
那么,当我删除这个 Widget 时,它的 WidgetFiles 会被删除,但重写的 delete() 方法并没有被触发,所以我在硬盘上做的那些额外操作没有执行。非常感谢任何帮助。
9 个回答
4
在删除之前使用 clear()
,可以把相关对象集合中的所有对象都移除。
可以参考这个链接了解更多内容:django-following-relationships-backward
示例:
group.link_set.clear()
group.delete()
83
我正在做同样的事情,注意到Django文档里有个小提示,你应该考虑一下。
重写删除 注意,当使用QuerySet批量删除对象时,并不一定会调用对象的delete()方法。为了确保自定义的删除逻辑能够执行,你可以使用pre_delete和/或post_delete信号。
这意味着你的代码片段并不总是能如你所愿。使用信号来处理删除操作会是更好的选择。
我选择了以下方法:
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)
47
我搞明白了。我在那个 Widget 模型上加了这个:
def delete(self):
files = WidgetFile.objects.filter(widget=self)
if files:
for file in files:
file.delete()
super(Widget, self).delete()
这样就会让每个相关的对象都执行必要的 delete() 方法,从而触发我自定义的文件删除代码。是的,这样对数据库的开销会更大,但如果你本来就是要删除硬盘上的文件,额外多访问几次数据库其实也没那么大的负担。