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

如何在Django CreateView中集成Ajax实现带文件上传的异步表单提交

问题原因排查

你遇到的报错和无响应问题核心是3个错误导致的:

  • 前端使用serialize()提交表单,该方法无法序列化文件类型的表单字段,且带文件上传的表单不能用普通序列化方式提交
  • 自定义的ajax_posting视图中,CreateProcedureForm参数传入顺序错误,导致表单无法正确接收POST数据,所以即使你填了内容也会报必填字段缺失
  • 自定义视图完全没有复用原有CreateView的验证、文件保存逻辑,属于重复开发,且逻辑不全导致提交后无对应反馈
最优改造方案

不用额外新增独立的AJAX视图,直接修改原有CreateProcedureView适配AJAX请求即可,同时修改前端提交逻辑:

1. 前端AJAX代码修改

使用FormData对象处理带文件的表单提交,调整AJAX配置:

$(document).ready(function (){
  $("#forms").on('submit', function(event) {
    event.preventDefault();
    // 直接用当前表单构建FormData,自动包含所有字段、文件和CSRF令牌
    var formData = new FormData(this);
    $.ajax({
        type: "POST",
        url: "{% url '你原来的CreateProcedureView对应的路由名' %}", // 无需使用新增的ajax_posting路由
        data: formData,
        datatype: 'json',
        // 必须添加这两个配置,禁止jQuery处理FormData
        processData: false,
        contentType: false,
        success: function(data) {
          if (data.success) {
            alert("提交成功");
            // 可自行添加跳转逻辑,比如 location.href = data.redirect_url
          } else {
            // 展示表单错误信息,可自行优化展示样式
            alert("提交失败:" + JSON.stringify(data.errors));
          }
        },
        error: function() {
          alert("请求异常,请重试");
        }
    });
  });
});

2. 原有CreateView改造

修改form_valid和form_invalid方法,适配AJAX请求返回JSON,原有普通提交逻辑完全保留:

from django.http import JsonResponse

class CreateProcedureView(LoginRequiredMixin,CreateView):
    model = NewProcedure
    form_class = CreateProcedureForm
    template_name = 'create_procedure.html'

    def form_valid(self, form):
        instance = form.save()
        # 判断是否是AJAX请求
        if self.request.headers.get('x-requested-with') == 'XMLHttpRequest':
            return JsonResponse({
                'success': True,
                'redirect_url': reverse('Procedures:procedure_main_menu')
            })
        # 普通提交走原有逻辑
        return super().form_valid(form)

    def form_invalid(self, form):
        # 判断是否是AJAX请求
        if self.request.headers.get('x-requested-with') == 'XMLHttpRequest':
            return JsonResponse({
                'success': False,
                'errors': form.errors.get_json_data()
            })
        # 普通提交走原有逻辑
        return super().form_invalid(form)

    def post(self, request, *args, **kwargs):
        if "cancel" in request.POST:
            redirect_url = reverse('Procedures:procedure_main_menu')
            if request.headers.get('x-requested-with') == 'XMLHttpRequest':
                return JsonResponse({'success': True, 'redirect_url': redirect_url})
            return HttpResponseRedirect(redirect_url)
        else:
            self.object = None
            user = request.user
            form_class = self.get_form_class()
            form = self.get_form(form_class)
            file_form = NewProcedureFilesForm(request.POST, request.FILES)
            files = request.FILES.getlist('file[]')
            if form.is_valid() and file_form.is_valid():
                procedure_instance = form.save(commit=False)
                procedure_instance.user = user
                procedure_instance.save()
                for f in files:
                    procedure_file_instance = NewProcedureFiles(attachments=f, new_procedure=procedure_instance)
                    procedure_file_instance.save()
                return self.form_valid(form)
            else:
                # AJAX请求时同时返回文件表单的错误
                if request.headers.get('x-requested-with') == 'XMLHttpRequest':
                    all_errors = form.errors.get_json_data()
                    all_errors.update(file_form.errors.get_json_data())
                    return JsonResponse({'success': False, 'errors': all_errors})
                return self.form_invalid(form)
注意事项
  • 如果你的CreateProcedureForm初始化时需要传入user参数,请在get_form_kwargs方法中添加,不要直接修改form实例化的参数顺序
  • 确保你的表单的enctype属性设置为multipart/form-data,否则文件无法正常提交

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 23:27:04