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

Django序列化器测试:含用户信息的文件上传请求报错解决

问题描述

我尝试测试包含用户信息的文件上传接口,编写了如下测试代码:

@deconstructible
class FileGenerator:

    @staticmethod
    def generate_text_file(file_ending='txt'):
        file_content = b'some test string'
        file = io.BytesIO(file_content)
        file.name = f'test.{file_ending}'
        file.seek(0)
        return file

def test_this(self, api_client, login_as):
    user = login_as('quality-controller')
    url = reverse('test-list')
    organization = Organization(name="test")
    organization.save()

    data = {
        "organization": organization.id,
        "import_file": FileGenerator.generate_text_file('txt'),
        "user": {
            "id": user.id,
            "username": user.username,
        }
    }

    response = api_client.post(url, data, format='json')

使用format='json'发送请求时,收到错误:

b'{"import_file": ["The submitted data was not a file. Check the encoding type on the form."]}'

改用format='multipart'时,又收到错误:

AssertionError: Test data contained a dictionary value for key 'user', but multipart uploads do not support nested data. You may want to consider using format='json' in this test case.


解决方法

方法1:扁平化嵌套的user数据(适配multipart格式)

multipart/form-data不支持嵌套字典,直接把user的字段拆成顶层键值对,保持文件字段不变即可:

data = {
    "organization": organization.id,
    "import_file": FileGenerator.generate_text_file('txt'),
    "user_id": user.id,
    "user_username": user.username,
}

response = api_client.post(url, data, format='multipart')

后端接口需要同步调整,要么直接接收这些扁平化字段,要么在逻辑层将字段重新组装成user字典。

方法2:Base64编码文件内容(适配JSON格式)

如果后端支持,把文件内容转成Base64字符串嵌入JSON数据中发送:

import base64

def test_this(self, api_client, login_as):
    user = login_as('quality-controller')
    url = reverse('test-list')
    organization = Organization(name="test")
    organization.save()

    # 将文件内容编码为Base64字符串
    file_content = b'some test string'
    base64_file = base64.b64encode(file_content).decode('utf-8')

    data = {
        "organization": organization.id,
        "import_file": {
            "filename": "test.txt",
            "content": base64_file,
            "content_type": "text/plain"
        },
        "user": {
            "id": user.id,
            "username": user.username,
        }
    }

    response = api_client.post(url, data, format='json')

后端需要对应做解码处理,把Base64字符串还原为文件内容。

方法3:将嵌套字段序列化为JSON字符串(适配multipart格式)

把user字典转成JSON字符串作为顶层字段值,后端再反序列化解析:

import json

data = {
    "organization": organization.id,
    "import_file": FileGenerator.generate_text_file('txt'),
    "user": json.dumps({
        "id": user.id,
        "username": user.username,
    }),
}

response = api_client.post(url, data, format='multipart')

后端接口中用json.loads()解析user字段的值,即可得到原字典结构。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 05:01:02