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

Django REST Framework文件上传报错:已传文件仍提示文件字段必填

问题原因

你的代码存在两个核心问题导致表单验证失败:

  1. 文件字段传递方式错误:Django的ModelForm处理上传文件时,文件字段必须通过files参数单独传递,不能和普通字段一起放在data参数里。你当前把file_store放到data中,表单无法识别这是上传文件,因此判定file_store字段为空,触发必填校验错误。
  2. upload_to路径生成逻辑错误:模型中file_store的upload_to使用f-string结合datetime.now(),会在模型类加载时就固定时间值,所有后续上传的文件都会存入同一个静态目录,无法实现动态生成上传路径的需求。
修复方案

1. 修正视图中表单初始化方式

将文件字段与普通字段拆分传递,文件字段通过files参数传入:

class FileViews(APIView):
    
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]
    
    def post(self,request):
        try:
            file = request.FILES.get("file")
            user_id = request.POST.get("user_id")  # 改用get避免KeyError
            
            if not file or not user_id:
                return Response({"message": "Both 'file' and 'user_id' are required."}, status=rest_framework.status.HTTP_400_BAD_REQUEST)

            # 拆分data和files参数,分别传递普通字段与文件字段
            file_form = FilesForm(
                data={"user_id": user_id},
                files={"file_store": file}
            )
            if file_form.is_valid():
                file_form.save()
                print(file_form.cleaned_data)
                response = {"message" : "File is uploaded"}
                return Response(response , status = rest_framework.status.HTTP_201_CREATED)
        
            else:
                response = {"message" : file_form.errors}
                return Response(response , status=rest_framework.status.HTTP_400_BAD_REQUEST)
        
        except Exception as e:
            print(e)
            response = {"message" : str(e)}
            return Response(response , status = rest_framework.status.HTTP_500_INTERNAL_SERVER_ERROR)

2. 修复模型的动态上传路径

改用可调用函数生成动态路径,确保每次上传都会生成新的时间目录:

import datetime
from django.db import models

def get_upload_path(instance, filename):
    # 按时间生成唯一目录,格式示例:20240520_143020/filename
    time_str = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
    return f"../uploads/{time_str}/{filename}"

class Files(models.Model):
    user_id = models.IntegerField(unique=True) 
    file_size = models.PositiveIntegerField("file size(in Bytes)", default=0)
    file_store = models.FileField(upload_to=get_upload_path)
    file_compressed = models.BooleanField(default=False)

3. 优化:自动填充文件大小(可选)

在表单中添加clean方法,自动从上传文件中获取文件大小,避免手动传递出错:

from django import forms
from .models import Files

class FilesForm(forms.ModelForm):
    class Meta:
        model = Files
        fields = '__all__'
    
    def clean(self):
        cleaned_data = super().clean()
        file = cleaned_data.get("file_store")
        if file:
            # 自动从文件对象中提取大小
            cleaned_data["file_size"] = file.size
        return cleaned_data

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 16:20:00