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

Django保存模型报'memoryview'无'_committed'属性错误排查

问题定位

'memoryview' object has no attribute '_committed'报错直接触发点是模型中的referral FileField字段。
Django的FileField在数据库中默认存储的是文件的相对路径字符串,文件实体存在配置的MEDIA_ROOT目录下;模型保存时Django会读取该字段绑定的文件对象的_committed属性判断文件是否已经落盘。当数据库中该字段存储的不是路径字符串,而是二进制memoryview/字节对象时,模型实例从数据库取出后,该字段的值就是非法的memoryview类型,一旦调用save()方法,Django处理FileField逻辑时找不到_committed属性就会抛出这个错误——哪怕你没有修改这个字段的内容,只要调用save()就会触发。
你提到的filter().update()不报错但不生效是两个独立问题:update()方法直接生成SQL执行,完全跳过模型层的字段校验、信号和预处理逻辑,所以不会触发FileField的校验逻辑;而更新不生效一般是filter条件未匹配到目标记录、数据库账号无写权限、事务未提交导致,和本次FileField报错无关。

排查步骤
  • 直接查询数据库appointments表的目标记录,查看referral字段存储的内容:如果字段值是二进制blob类型、不是合法的文件路径字符串/NULL,就是脏数据导致的问题。
  • 全局搜索所有给Appointments.referral赋值的代码,排查是否存在直接给字段赋值二进制内容、memoryview对象、文件读取结果的错误写法,常见错误写法包括直接赋值request.FILES['xxx'].read()的返回值、手动生成的内存缓冲区对象。
  • 检查数据库表结构,确认referral字段类型是varchar/text类型,没有被手动改成blob/binary二进制类型。
修复方案
  1. 先清理脏数据:将表中referral字段存储的非法二进制内容清空,或者替换为MEDIA_ROOT/referrals目录下实际存在的文件对应相对路径,此时再测试仅查询实例直接调用save()的极简逻辑,报错会直接消失。
  2. 修正FileField的赋值逻辑,禁止直接给字段赋值二进制/缓冲区对象:
    错误写法示例(必然触发同类报错):
    # 直接赋值二进制内容
    app_obj.referral = b'file binary content'
    # 直接赋值memoryview对象
    app_obj.referral = memoryview(b'file binary content')
    # 赋值文件读取后的字节结果
    app_obj.referral = request.FILES['referral_file'].read()
    
    正确写法示例:
    # 直接绑定上传的文件对象
    app_obj.referral = request.FILES['referral_file']
    
    # 如果需要从内存二进制内容生成文件,用ContentFile包装
    from django.core.files.base import ContentFile
    # 注意save=False避免重复触发模型保存
    app_obj.referral.save('referral_file.pdf', ContentFile(binary_content), save=False)
    
  3. 如果你确实需要将文件二进制内容直接存入数据库,不要使用FileField,替换为models.BinaryField即可,不过这种方案读写效率极低,不推荐在项目中使用。
  4. 排查update()方法不生效的问题:先在Django shell中执行对应filter查询确认匹配到了目标记录,再检查数据库连接账号是否对该表有UPDATE权限,是否存在事务未提交的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 20:12:26