You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django使用post_save存储ImageField图片base64时报FileNotFound错误

问题诱因
  • 路径调用错误:instance.thumbnail.url返回的是面向HTTP访问的资源路径(比如报错信息里的/media/feeds/sisi_q1f0hdr.jpeg),不是本地文件系统的物理路径,open()方法只能读取本地路径的文件,所以直接触发文件不存在错误,需要改用instance.thumbnail.path获取文件在服务器上的真实存储路径。
  • 字段名不匹配:模型里定义的base64存储字段是img_b64,但信号代码里赋值的是instance.image_b64,字段名写错,就算路径正确也无法把值写入对应字段。
  • 存在无限递归风险:post_save信号是实例保存完成后触发的,你在信号里又调用instance.save(),会再次触发post_save信号,形成无限循环,最终会导致程序崩溃。
更优实现方案

推荐直接重写模型的save()方法实现需求,比信号逻辑更直观,也更容易避免递归问题,代码如下:

import base64
from django.db import models
# 保留原有其他导入内容

class Feed(models.Model):
    # 原有模型字段全部保留不变
    id = models.BigAutoField(primary_key=True)
    title = models.CharField(max_length = 200)
    content = models.TextField()
    thumbnail = models.ImageField(upload_to='feeds/', blank=True)
    img_b64 = models.BinaryField(blank=True, null=True)
    author = models.ForeignKey(Account, on_delete=models.CASCADE)
    date = models.DateTimeField(auto_now_add=True)
    view = models.IntegerField(default=0)
    kategori = models.CharField(max_length=100, default="None")

    def save(self, *args, **kwargs):
        # 先执行原生保存逻辑,确保缩略图已经写入磁盘
        super().save(*args, **kwargs)
        # 仅当有缩略图且未生成过base64时处理,避免重复操作
        if self.thumbnail and not self.img_b64:
            # 用path属性获取本地真实路径读取文件
            with open(self.thumbnail.path, "rb") as img_file:
                self.img_b64 = base64.b64encode(img_file.read())
            # 只更新base64字段,避免再次触发全量保存逻辑
            super().save(update_fields=['img_b64'])

如果一定要用post_save信号实现,修改后的代码如下:

@receiver(post_save, sender=Feed)
def save_base64(sender, instance, created, **kwargs):
    # 仅在实例首次创建、有缩略图、base64字段为空时处理
    if created and instance.thumbnail and not instance.img_b64:
        with open(instance.thumbnail.path, "rb") as img_file:
            instance.img_b64 = base64.b64encode(img_file.read())
        # 仅更新指定字段,避免触发post_save递归
        instance.save(update_fields=['img_b64'])

注意:把图片base64存入数据库会大幅增加数据库体积,拖慢查询效率,非必要场景不推荐这么使用。如果是为了前端渲染直接返回base64,也可以在接口层动态读取图片生成base64返回,不用持久化存储到库中。

内容的提问来源于stack exchange,提问作者Andi Fathul Mukminin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 04:24:01