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

Django使用ModelForm上传CSS文件时获取失败、校验不生效如何解决

问题根本原因

  1. 前端表单未配置enctype="multipart/form-data"属性:浏览器提交带文件的表单时必须指定该编码类型,否则只会将文件名作为普通字符串传到request.POST,不会将文件内容写入request.FILES,这就是你看到request.FILES为空、request.POST['file']只有文件名的核心原因。
  2. 自定义字段的异常捕获逻辑不合理:当没有拿到文件对象触发AttributeError时你直接pass跳过了校验,所以就算没有上传有效文件,表单也会判定为合法。
  3. 视图函数的POST处理分支缺少返回值,Django要求所有请求分支都必须返回HttpResponse对象,否则会触发运行错误。

修复步骤

1. 修改前端模板表单

给<form>标签加上编码类型属性:

<form method="POST" enctype="multipart/form-data">
    {% csrf_token %}
    <div class="form-title">Upload a new CSS file</div>
    {{ form.as_p }}
    <div class="button-area">
        <button id="go" type="submit">Go</button>
    </div>
</form>

2. 优化自定义FileField逻辑

  • 修改max_upload_size的默认值为数值类型,避免后续比较报错
  • 调整异常捕获逻辑,文件为空时主动抛出校验错误
class FileField(models.FileField):
    def __init__(self, *args, **kwargs):
        self.content_types = kwargs.pop('content_types', [])
        # 修改默认值为数值类型,默认最大5MB
        self.max_upload_size = kwargs.pop('max_upload_size', mb(5))
        super().__init__(*args, **kwargs)
    
    def clean(self, *args, **kwargs):
        data = super().clean(*args, **kwargs)
        # 先判断是否拿到了文件
        if not data:
            raise forms.ValidationError('请选择要上传的文件')
        file = data.file

        try:
            content_type = file.content_type
            if content_type in self.content_types:
                if file.size > self.max_upload_size:
                    raise forms.ValidationError('请保持文件大小在 {} 以内,当前文件大小为 {}'
                    .format(filesizeformat(self.max_upload_size), filesizeformat(file.size)))
            else:
                raise forms.ValidationError('不支持的文件格式,请上传CSS文件')
        except AttributeError:
            raise forms.ValidationError('文件读取失败,请重新上传')
        return data

3. 修复视图函数返回逻辑

给POST请求分支添加返回值,校验成功后可以保存文件或者返回成功提示,校验失败返回带错误信息的表单:

def cssUploadView(request):
    if request.method == 'POST':
        form = forms.CssCreateForm(request.POST, request.FILES)
        if form.is_valid():
            # 校验成功可以执行保存操作
            form.save()
            print('---------')
            print(form.cleaned_data['file'])
            # 可根据需求跳转到成功页或者返回成功提示
            return HttpResponse('上传成功')
        else:
            print('not valid')
    else:
        form = forms.CssCreateForm()
    # 把POST校验失败的分支和GET分支的返回统一放到最后
    return render(request, 'css/css_create.html', {
        'form': form,
    })

额外优化建议

仅校验content-type很容易被伪造,你可以额外增加文件内容校验,比如读取文件前若干字符判断是否为合法CSS格式,避免用户修改后缀绕过校验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 22:54:06