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

使用POST提交非Django模板表单时遇CSRF Token错误的解决咨询

Alright, let's tackle that CSRF token error you're getting when submitting a non-Django-template form via POST. I've looked at your view code, and here's how to fix this properly (plus some context so you understand why it's happening):


Why this error happens

Django's built-in CSRF protection middleware checks every POST request for a valid CSRF token to prevent cross-site request forgery attacks. When you use Django templates, the {% csrf_token %} tag automatically adds a hidden input with the token, but since you're not using Django templates, you have to handle this manually.


This is the secure, production-ready approach. We'll update your view to expose the CSRF token, then add it to your form or request headers when submitting.

Step 1: Modify your view to return the CSRF token

Add a get method to your class-based view and use Django's get_token utility to fetch and return the token:

from django.middleware.csrf import get_token
from django.http import JsonResponse, HttpResponse
from django.views.generic import View

class YourFormView(View):  # Replace with your actual view name
    form_class = YourFormClass  # Replace with your form class

    def get(self, request):
        # Retrieve the CSRF token from the request context
        csrf_token = get_token(request)
        
        # Option 1: Return as JSON (ideal for AJAX/SPA frontends)
        return JsonResponse({'csrf_token': csrf_token})
        
        # Option 2: Return custom HTML with embedded token (if serving raw HTML)
        # html_content = f'''
        # <form method="POST" enctype="multipart/form-data">
        #     <input type="hidden" name="csrfmiddlewaretoken" value="{csrf_token}">
        #     <!-- Add your form fields here -->
        #     <input type="email" name="email" required>
        #     <input type="file" name="file">
        #     <button type="submit">Submit</button>
        # </form>
        # '''
        # return HttpResponse(html_content)

    def post(self, request):
        # Your existing post logic remains unchanged
        form = self.form_class(request.POST or None, request.FILES or None)
        if form.is_valid():
            email = form.cleaned_data.get('email')
            user = authenticate(email=email)
            if user is None:
                form.save()
                message = 'Saved Successfully'
                return HttpResponse(message)
            else:
                message = 'User Exists'
                return HttpResponse(message)
        else:
            message = 'Invalid form data'
            return HttpResponse(message)

Step 2: Include the token in your POST request

  • Plain HTML form: Add a hidden input field with the token value you retrieved from the get request.
  • AJAX (fetch/axios): Add the token to the request headers as X-CSRFToken:
    // Example with fetch API
    fetch('/your-view-url/', {
      method: 'POST',
      headers: {
        'X-CSRFToken': 'YOUR_CSRF_TOKEN_FROM_GET_REQUEST',
      },
      body: new FormData(document.getElementById('your-form-id'))
    })
    
    // Example with axios
    axios.post('/your-view-url/', formData, {
      headers: {
        'X-CSRFToken': 'YOUR_CSRF_TOKEN_FROM_GET_REQUEST'
      }
    })
    

If you're just testing and need a quick workaround (never use this in production), you can exempt the view from CSRF checks:

from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator

@method_decorator(csrf_exempt, name='dispatch')
class YourFormView(View):
    # Your existing post method here
    def post(self, request):
        # ... same as before ...

Warning: This disables a critical security feature, so only use this for local testing or internal tools where CSRF attacks aren't a risk.


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:40:53