如果前端依赖 Django 模板 + form,耦合高、异常处理也不方便。

更稳的方式是:前端用 FormData + Ajax 上传,后端仅接收文件,返回 JSON。

前端代码

file_upload.html

<form id="id_ajax_upload_form" class="ui form" method="post" onkeypress="return event.keyCode !== 13;">
  <div class="field">
    <label>User IDs:</label>
    <input type="file" id="user_ids" name="user_ids" />
  </div>
  {% csrf_token %}
  <button class="upload ui teal button">Upload</button>
</form>

Ajax 请求

$(".upload").click(function (e) {
  const form = $("form")[0];
  const formData = new FormData(form);

  if (form.checkValidity()) {
    e.preventDefault();
    $.ajax({
      url: "/upload",
      type: "POST",
      data: formData,
      success: function (data) {
        if (data.success) {
          alert("Success");
        } else {
          alert("Fail: " + data.errors);
        }
      },
      enctype: "multipart/form-data",
      cache: false,
      contentType: false,
      processData: false,
    });
  }
});

说明:

  • contentType: falseprocessData: false 是关键,否则文件会被错误序列化。
  • 若启用 CSRF,需要确保请求携带 CSRF token(模板里已有 {% csrf_token %})。

后端代码

直接读取 request.FILES

from django.http import JsonResponse

def upload(request):
    my_file = request.FILES.get("my_file")
    if not my_file:
        return JsonResponse({"success": False, "errors": "file required"})

    # 处理文件...
    return JsonResponse({"success": True})

使用表单验证

forms.py

from django import forms

class MyForm(forms.Form):
    my_file = forms.FileField(allow_empty_file=False)

views.py

from django.http import JsonResponse
from django.shortcuts import render
from .forms import MyForm

def upload(request):
    if request.method == "POST":
        form = MyForm(request.POST, request.FILES)
        if form.is_valid():
            # form.save()  # 如果是 ModelForm
            return JsonResponse({"success": True, "message": "Uploaded Successfully"})
        return JsonResponse({"success": False, "errors": form.errors})

    return render(request, "file_upload.html", {"form": MyForm()})

小结

  • 前端用 FormData + Ajax,后端只管接收和校验。
  • 返回 JSON,异常处理更干净。
  • 想要更清晰的错误信息,可以在后端统一封装响应结构。

参考