You need to enable JavaScript to run this app. Django pytest测试GraphQL上传:SimpleUploadedFile序列化错误修复
优惠活动
大模型
产品
解决方案
定价
更多

Django pytest测试GraphQL上传:SimpleUploadedFile序列化错误修复

报错根本成因
  • 错误根源是把SimpleUploadedFile文件对象直接放到了需要被JSON序列化的GraphQL普通请求参数里。
  • 你代码里依赖的client_query fixture,默认实现是按照application/json格式构造请求:会把传入的input_data/variables字典整体丢给Python原生json模块做序列化生成请求体。而SimpleUploadedFile是Django自定义的文件类,不属于json模块支持的可序列化原生类型,序列化到这一步就会直接抛出not JSON serializable错误。
  • 从协议层面讲,GraphQL的文件上传本身就不支持把文件内容塞到JSON请求体里,官方约定的文件上传必须走multipart/form-data格式,要单独拆分文件块、配置变量和文件的映射关系,当前的传参方式从协议规范上就是不兼容的。
具体修复方案
  • 改造测试client的逻辑,使其支持GraphQL multipart上传协议:不要无脑把所有参数都做JSON序列化,当检测到存在文件类型参数时,自动切换成multipart格式构造请求,严格按照规范拆分三个请求段:
    • operations段:存储GraphQL查询语句、非文件类型的普通变量,文件对应的变量位置先设为null
    • map段:建立上传文件和查询变量路径的对应关系
    • 文件段:单独携带每个待上传的文件内容
  • 把原来塞在input_data里的SimpleUploadedFile对象抽离,不要让它进入JSON序列化流程,单独通过client的文件参数传入。
  • 修正代码里的隐藏配置错误:你定义的mutation操作名是uploadImage,但调用时传的op_name是uploadMessageImage,就算解决了序列化问题,后续也会因为操作名不匹配触发请求报错,需要把op_name改成和query定义一致的名称。

修正后的测试调用示例参考:

def test_non_authenticated_request(self, user, client, client_query):
    # 单独构造测试文件对象
    test_file = SimpleUploadedFile(
        name='test_image.jpg',
        content=b'fake jpeg binary content',
        content_type='image/jpeg'
    )
    # 变量字典里移除文件对象,对应位置设为null等待映射
    input_data = {"file": None}
    response = client_query(
        self.query,
        op_name="uploadImage",  # 和query中定义的mutation名保持一致
        variables=input_data,
        # 单独传入文件、配置映射关系,由client自动生成符合规范的multipart请求
        files={"0": test_file},
        map={"0": ["variables.file"]}
    )

    content = json.loads(response.content)
    assert "errors" not in content
    assert AuthenticationError.__name__ in str(response.content)

内容的提问来源于stack exchange,提问作者Aaron Sta.Clara

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.06 14:36:03