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

原生JavaScript实现Django表单AJAX提交:无法传FormData及判断请求类型

Fixing Native JS AJAX Form Submission to Django

Hey there! Let’s work through those two roadblocks you’re hitting with native JavaScript AJAX and Django—they’re super common when moving away from jQuery, so I’ve got step-by-step fixes for both.

1. Sending FormData to Django Successfully

The main issues here are missing CSRF token handling and incorrect request headers (which jQuery handles automatically). Here’s how to fix it:

Frontend Native JS Code

const registerForm = document.getElementById('register-form');

registerForm.addEventListener('submit', (e) => {
  e.preventDefault(); // Prevent default form submission

  // Create FormData from the form element
  const formData = new FormData(registerForm);

  // Initialize XMLHttpRequest
  const xhr = new XMLHttpRequest();
  xhr.open('POST', '/register/', true);

  // Add Django's required CSRF token (critical for security)
  const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value;
  xhr.setRequestHeader('X-CSRFToken', csrfToken);

  // DO NOT manually set Content-Type! Let the browser handle it automatically
  // This ensures FormData is encoded correctly as multipart/form-data

  // Handle response
  xhr.onload = () => {
    if (xhr.status >= 200 && xhr.status < 300) {
      const response = JSON.parse(xhr.responseText);
      console.log('Registration success:', response);
      // Add your success UI updates here
    } else {
      const errorResponse = JSON.parse(xhr.responseText);
      console.error('Registration failed:', errorResponse);
      // Add your error handling UI here
    }
  };

  // Send the FormData
  xhr.send(formData);
});

Backend Django View Adjustment

If your form includes file uploads, make sure to pass request.FILES to the form constructor. For regular text fields, request.POST works fine, but including request.FILES is safe either way:

def register(request):
    if request.method == "POST":
        # Include request.FILES if your form has file fields
        form = RegisterForm(request.POST, request.FILES)
        if form.is_valid():
            # We'll handle the AJAX check next
            # ... save form data here ...

2. Detecting AJAX Requests in Django

Django’s request.is_ajax() was deprecated in version 3.1, and it relied on a header that jQuery automatically adds—but native JS doesn’t. Here’s how to fix this:

Step 1: Add the AJAX Identifier Header in JS

Add this line right after setting the CSRF token in your JavaScript:

xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');

Step 2: Replace request.is_ajax() with Manual Header Check

Update your view to check for the header we just added:

def register(request):
    if request.method == "POST":
        form = RegisterForm(request.POST, request.FILES)
        if form.is_valid():
            # Manually check if the request is AJAX
            is_ajax_request = request.headers.get('X-Requested-With') == 'XMLHttpRequest'
            
            if is_ajax_request:
                # Handle AJAX submission: return JSON response
                form.save() # Save the valid form data
                return JsonResponse({'status': 'success', 'message': 'Registered!'})
            else:
                # Handle regular form submission: redirect or render page
                form.save()
                return redirect('dashboard')
        else:
            # Handle invalid form
            is_ajax_request = request.headers.get('X-Requested-With') == 'XMLHttpRequest'
            if is_ajax_request:
                # Return errors as JSON for AJAX
                return JsonResponse({'status': 'error', 'errors': form.errors}, status=400)
            else:
                # Re-render form with errors for regular submission
                return render(request, 'register.html', {'form': form})
    else:
        # GET request: show empty form
        form = RegisterForm()
        return render(request, 'register.html', {'form': form})

Key Takeaways

  • Always include the CSRF token in your native JS AJAX requests—Django blocks requests without it.
  • Never manually set Content-Type when sending FormData; let the browser handle encoding.
  • Replace the deprecated request.is_ajax() with a check for the X-Requested-With header, which you need to add manually in your JS.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 03:25:06