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

Django:创建含ImageField的模型实例报错,如何保存图片到Media?

解决Django ImageField保存PNG图片报错问题

错误原因

直接将PIL的PngImageFile对象传给ImageField会触发报错,因为Django的ImageField仅接受符合其文件接口的对象(如InMemoryUploadedFile),而非PIL图像实例,所以才会出现'PngImageFile' object has no attribute '_committed'错误。

解决方案

把转换后的PNG字节流包装成InMemoryUploadedFile对象,Django会自动将文件保存到upload_to指定的media目录,同时将文件路径存入数据库。

修改后的代码

views.py

from django.core.files.uploadedfile import InMemoryUploadedFile
import sys

def upload_drawings(request):
    if request.method == "POST":
        form = DrawingPDFForm(request.POST, request.FILES)
        if form.is_valid():
            drawing_name = form.cleaned_data['drawing_name']
            file = form.cleaned_data['file']
            pdf_content = BytesIO(file.read()) 
            pdf_converted = convert_from_bytes(pdf_content.read(), poppler_path=r"C:\Python\Python\Programs\plant_locator\poppler\poppler-23.07.0\Library\bin")
            
            # 处理PDF转PNG,移除冗余的base64编解码步骤
            buffer = BytesIO()
            pdf_converted[0].save(buffer, format='PNG')
            buffer.seek(0)  # 重置字节流指针到起始位置
            
            # 自定义PNG文件名,保留原PDF文件名前缀
            filename = f"{file.name.rsplit('.', 1)[0]}.png"
            
            # 将字节流包装为Django可识别的文件对象
            png_file = InMemoryUploadedFile(
                buffer,
                None,
                filename,
                'image/png',
                sys.getsizeof(buffer),
                None
            )
            
            # 创建模型实例并保存
            Drawing.objects.create(drawing_name=drawing_name, drawing=png_file)
            return HttpResponseRedirect('/upload_drawings')
    else:
        form = DrawingPDFForm()
    return render(request, 'upload_drawings.html', {'form':form})

关键修改点

  • 移除了不必要的base64编解码操作,直接通过BytesIO处理图像字节流,提升效率
  • 用InMemoryUploadedFile将PNG字节流包装为Django兼容的文件对象
  • 添加表单验证form.is_valid(),改用cleaned_data获取数据,避免直接操作请求原始数据的安全风险
  • 自定义PNG文件名,保留原PDF的名称前缀,便于文件溯源

必要配置检查

  1. 确保settings.py中已配置media相关参数:
    # settings.py
    MEDIA_ROOT = BASE_DIR / 'media'
    MEDIA_URL = '/media/'
    
  2. 在项目urls.py中添加media路径映射:
    from django.conf import settings
    from django.conf.urls.static import static
    
    urlpatterns = [
        # 其他URL配置
    ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    

内容的提问来源于stack exchange,提问作者Bleached

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 07:20:08