Django通过signal(信号)实现对所有的model(模型)删除记录时自动删除FileField、ImageField字段的文件

作者在 2021-07-07 17:15:58 发布以下内容

假设startapp创建的app为app1

在app1中创建一个helpers模块,加入如下代码:

from django.db import models
from django.db.models.signals import pre_delete
from django.dispatch import receiver


def bind_delete_signal(model):
    @receiver(pre_delete, sender=model)
    def pre_model_delete(sender, **kwargs):
        for field in sender._meta.get_fields():
            if isinstance(field, models.FileField) or isinstance(field, models.ImageField):
                instance = kwargs.get('instance')
                getattr(instance, field.name).delete()

在apps.py中的App1Config类中重写ready方法:

    def ready(self):
        from app1.helpers import bind_delete_signal

        for model in self.get_models():
            bind_delete_signal(model)

这样,在删除模型实例的时候,只要模型实例有 FileField 和 ImageField 相关的字段,就会自动删除相关的文件

作者在 2022-03-16 18:08:15 补充以下内容

新增缩略图功能,同样是监听信号,增加监听保存的动作,如果有新上传的图片,则自动生成缩略图

helpers模块:

import os
import time
from django.db import models
from django.db.models.signals import pre_delete, post_save
from django.dispatch import receiver


def bind_signal(model):
    @receiver(pre_delete, sender=model)
    def pre_model_delete(sender, **kwargs):
        for field in sender._meta.get_fields():
            if isinstance(field, models.FileField) or isinstance(field, models.ImageField):
                instance = kwargs.get('instance')
                img = getattr(instance, field.name)

                # 尝试删除缩略图(如果有的话)
                ext = os.path.splitext(img.path)[1]
                try:
                    os.remove("{path}.thumb{ext}".format(path=img.path, ext=ext))
                except Exception as e:
                    print('bind_signal.pre_model_delete.thumb: {0}'.format(e))

                # 删除原图片
                try:
                    img.delete()
                except Exception as e:
                    print('bind_signal.pre_model_delete: {0}'.format(e))

    @receiver(post_save, sender=model)
    def post_model_save(sender, **kwargs):
        for field in sender._meta.get_fields():
            if isinstance(field, models.ImageField):
                instance = kwargs.get('instance')
                img = getattr(instance, field.name)
                if img and time.time() - os.path.getctime(img.path) < 3 and img.size > 1024 * 1024 and (img.width > 1920 or img.height > 1200):
                    ext = os.path.splitext(img.path)[1]
                    os.system("convert {file_path} -resize 1920x1200 {file_path}.thumb{ext}".format(file_path=img.path, ext=ext))


在apps.py中的App1Config类中重写ready方法:

    def ready(self):
        from app1.helpers import bind_signal

        for model in self.get_models():
            bind_signal(model)

Python | 阅读 1098 次
文章评论,共0条
游客请输入验证码
浏览2800623次
文章归档