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

Django单元测试:如何用APIClient上传CSV文件并解决报错

解决DRF文件上传单元测试的"Missing filename"报错

我来帮你分析问题并给出修复方案:

问题背景

你在为Django REST Framework的ChartOfAccounts视图编写单元测试,用于验证CSV文件上传功能,使用了自定义的_file_upload辅助方法,但遇到了如下报错:

Missing filename. Request should include a Content-Disposition header with a filename parameter.

你的测试辅助方法代码:

@staticmethod
def _file_upload(client, string, args, file_name):
    base_path = os.path.dirname(os.path.realpath(__file__))
    with open(base_path + file_name, 'rb') as data:
        data = { 'file': data }
        response = client.post(reverse(string, args=[args]), data, format = "multipart")
        return response.status_code, response.data

待测试的视图代码:

class ChartOfAccounts(views.APIView):
    parser_classes = (JSONParser, FileUploadParser)
    def post(self, request, pk, *args, **kwargs):
        request.FILES['file'].seek(0)
        csv_data = CSVUtils.format_request_csv(request.FILES['file'])
        try:
            coa_data = CSVUtils.process_chart_of_accounts_csv(company, csv_data)
            serializer = CoASerializer(coa_data, many=True)
            if len(serializer.data) > 0:
                return Utils.dispatch_success(request, serializer.data)
        except Exception as e:
            error = ["%s" % e]
            return Utils.dispatch_failure(request, 'DATA_PARSING_ISSUE', error)

错误原因

你的视图配置了FileUploadParser,这个解析器要求上传的文件必须携带包含filename参数的Content-Disposition请求头。但你当前的测试代码只是直接将打开的文件对象放入data字典,Django测试客户端不会自动为该文件对象添加符合要求的请求头,因此触发了解析器的报错。

解决方案

最简便的修复方式是使用Django提供的SimpleUploadedFile构造上传文件对象,它会自动帮你处理文件名及对应的请求头信息。修改你的测试方法如下:

from django.core.files.uploadedfile import SimpleUploadedFile
import os

@staticmethod
def _file_upload(client, string, args, file_name):
    base_path = os.path.dirname(os.path.realpath(__file__))
    # 用os.path.join拼接路径更安全,避免不同系统的路径分隔符问题
    file_path = os.path.join(base_path, file_name)
    
    with open(file_path, 'rb') as f:
        # 构造包含文件名、文件内容和MIME类型的上传对象
        uploaded_file = SimpleUploadedFile(
            name=file_name,
            content=f.read(),
            content_type='text/csv'
        )
        data = {'file': uploaded_file}
        response = client.post(
            reverse(string, args=[args]),
            data,
            format='multipart'
        )
        return response.status_code, response.data

额外提示

顺便注意:你的视图post方法中用到了company变量,但代码里没有看到它的定义逻辑,比如是否应该通过pk参数查询获取?例如:

from django.shortcuts import get_object_or_404

# 在post方法开头添加
company = get_object_or_404(Company, pk=pk)

如果遗漏这一步,后续运行时会抛出NameError,记得补上。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 03:56:15