移动文件后django-imagekit报The file cannot be reopened错误如何解决
错误原因
你启用Optimistic缓存策略后,django-imagekit会在绑定源字段(这里是thumbnail)第一次调用save()时就立即触发缩略图生成逻辑,此时你还没有移动原始文件,imagekit已经持有了旧路径的文件对象。等你移动文件、更新thumbnail路径后第二次调用save()时,旧文件对象指向的路径已经不存在,且Django的File对象关闭后不支持重新打开,就触发了报错。
解决方案
你只需要调整save()逻辑里临时禁用首次保存时的imagekit自动生成,等文件移动完成后再触发缩略图生成即可,修改后的代码如下:
首先导入工具方法:
import os from django.conf import settings from imagekit.utils import disable_auto_generate
然后修改模型的save()方法:
def save(self, *args, **kwargs): # 第一次保存时禁用自动生成,避免未移动文件就触发缩略图生成 with disable_auto_generate(): super().save(*args, **kwargs) if self.thumbnail and "/new/" not in self.thumbnail.path: # 移动缩略图到正确位置 initial_name = self.thumbnail.name initial_path = self.thumbnail.path new_name = os.path.join(os.path.dirname(initial_name), "new", os.path.basename(initial_name)) new_path = os.path.join(settings.MEDIA_ROOT, new_name) if not os.path.exists(os.path.dirname(new_path)): os.makedirs(os.path.dirname(new_path)) os.rename(initial_path, new_path) self.thumbnail.name = new_name # 清空字段缓存的旧文件对象,强制下次访问时从新路径加载 self.thumbnail._file = None kwargs["force_insert"] = False # 第二次保存会正常触发imagekit缩略图生成,此时使用的是更新后的文件路径 super().save(*args, **kwargs)
补充说明
如果不想用上下文管理器禁用自动生成,也可以在移动文件后手动调用缩略图字段的生成方法:
# 移动完文件、更新thumbnail路径后添加 from imagekit.cachefiles import LazyCacheFile cache_file = LazyCacheFile(self.list_thumbnail) cache_file.generate()
这种方式可以跳过信号触发逻辑,也能避免报错。
内容的提问来源于stack exchange,提问作者Phil Gyford
相关产品推荐
相关产品推荐

