The same URL may work normally with a GET request, but return a 403 error when submitting data with POST. This is usually because Django's CSRF validation has failed.
Django enables CSRF protection by default. As long as the project is configured with:
'django.middleware.csrf.CsrfViewMiddleware',
POST requests must include a valid CSRF token. Otherwise, Django will reject the request and return 403.
Recommended Method: Submit a CSRF Token
For a regular form, add the following inside the <form> tag in the template:
<form method="post">
{% csrf_token %}
<!-- form fields -->
<button type="submit">Submit</button>
</form>
Django will generate a hidden field in the page, which will be submitted together with the POST request, allowing CSRF validation to pass.
For Ajax requests, the CSRF token needs to be placed in the request headers. A common approach is to read csrftoken from the cookie and send it with the POST request:
fetch('/your-url/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken
},
body: JSON.stringify({ name: 'value' })
})
Method 1: Disable the CSRF Middleware
You can comment out this line in settings.py:
'django.middleware.csrf.CsrfViewMiddleware',
This way, POST requests will no longer return 403 because of failed CSRF validation.
However, this disables CSRF protection for the entire project, so it is not recommended for production environments. Unless you are testing locally or working with a very clearly defined internal API scenario, you should prioritize using a CSRF token.
Method 2: Disable CSRF Validation for a Single View
If only one specific endpoint does not need CSRF validation, you can add @csrf_exempt before the view's request handler:
# views.py
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def index(request):
return HttpResponse('ok')
This approach only affects the decorated view, so its scope is smaller than disabling the entire middleware. However, it still causes that endpoint to bypass CSRF protection, so it should only be used when truly necessary, such as for third-party callback endpoints, internal service endpoints, or APIs that already have other authentication and signature mechanisms.
