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
相关产品推荐
相关产品推荐

