Django CSRF Cookie Not Set
Question:
I have some problem for a while now, I’m experiencing CSRF Cookie not set. Please look at the code below:
views.py:
def deposit(request, account_num):
if request.method == 'POST':
account = get_object_or_404(account_info, acct_number=account_num)
form_ = AccountForm(request.POST or None, instance=account)
form = BalanceForm(request.POST)
info = str(account_info.objects.filter(acct_number=account_num))
inf = info.split()
if form.is_valid():
# cd=form.cleaned_data
now = datetime.datetime.now()
cmodel = form.save()
cmodel.acct_number = account_num
# RepresentsInt(cmodel.acct_number)
cmodel.bal_change = "%0.2f" % float(cmodel.bal_change)
cmodel.total_balance = "%0.2f" % (float(inf[1]) + float(cmodel.bal_change))
account.balance = "%0.2f" % float(cmodel.total_balance)
cmodel.total_balance = "%0.2f" % float(cmodel.total_balance)
# cmodel.bal_change=cmodel.bal_change
cmodel.issued = now.strftime("%m/%d/%y %I:%M:%S %p")
account.recent_change = cmodel.issued
cmodel.save()
account.save()
return HttpResponseRedirect("/history/" + account_num + "/")
else:
return render_to_response('history.html',
{'account_form': form},
context_instance=RequestContext(request))
Template file:
<form action="/deposit/{{ account_num }}/" method="post">
<table>
<tr>
{{ account_form.bal_change }}
<input type="submit" value="Deposit"/>
</tr>
{% csrf_token %}
</table>
</form>
I’n stuck, I already cleared the cookie, used other browser but still csrf cookie not set.
Answers:
try to check if your have installed in the settings.py
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',)
In the template the data are formatted with the csrf_token:
<form>{% csrf_token %}
</form>
In your view are you using the csrf decorator??
from django.views.decorators.csrf import csrf_protect
@csrf_protect
def view(request, params):
....
Problem seems that you are not handling GET
requests appropriately or directly posting the data without first getting the form.
When you first access the page, client will send GET
request, in that case you should send html with appropriate form.
Later, user fills up the form and sends POST
request with form data.
Your view should be:
def deposit(request,account_num):
if request.method == 'POST':
form_=AccountForm(request.POST or None, instance=account)
if form.is_valid():
#handle form data
return HttpResponseRedirect("/history/" + account_num + "/")
else:
#handle when form not valid
else:
#handle when request is GET (or not POST)
form_=AccountForm(instance=account)
return render_to_response('history.html',
{'account_form': form},
context_instance=RequestContext(request))
Check that chrome’s cookies are set with default option for websites. Allow local data to be set (recommended).
Method 1:
from django.shortcuts import render_to_response
return render_to_response(
'history.html',
RequestContext(request, {
'account_form': form,
})
Method 2:
from django.shortcuts import render
return render(request, 'history.html', {
'account_form': form,
})
Because render_to_response
method may case some problem of response cookies.
This problem arose again recently due to a bug in Python itself.
http://bugs.python.org/issue22931
https://code.djangoproject.com/ticket/24280
Among the versions affected were 2.7.8 and 2.7.9.
The cookie was not read correctly if one of the values contained a [
character.
Updating Python (2.7.10) fixes the problem.
I have just met once, the solution is to empty the cookies.
And may be changed while debugging SECRET_KEY
related.
Clearing my browser’s cache fixed this issue for me. I had been switching between local development environments to do the django-blog-zinnia tutorial after working on another project when it happened. At first, I thought changing the order of INSTALLED_APPS
to match the tutorial had caused it, but I set these back and was unable to correct it until clearing the cache.
From This
You can solve it by adding the ensure_csrf_cookie decorator to your view
from django.views.decorators.csrf import ensure_csrf_cookie
@ensure_csrf_cookie
def yourView(request):
#...
if this method doesn’t work. you will try to comment csrf in middleware. and test again.
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def your_view(request):
if request.method == "POST":
# do something
return HttpResponse("Your response")
I was using Django 1.10 before.So I was facing this problem.
Now I downgraded it to Django 1.9 and it is working fine.
Make sure your django session backend is configured properly in settings.py. Then try this,
class CustomMiddleware(object):
def process_request(self,request:HttpRequest):
get_token(request)
Add this middleware in settings.py
under MIDDLEWARE_CLASSES
or MIDDLEWARE
depending on the django version
get_token – Returns the CSRF token required for a POST form. The token is an alphanumeric value. A new token is created if one is not already set.
If you’re using the HTML5 Fetch API to make POST requests as a logged in user and getting Forbidden (CSRF cookie not set.)
, it could be because by default fetch
does not include session cookies, resulting in Django thinking you’re a different user than the one who loaded the page.
You can include the session token by passing the option credentials: 'include'
to fetch:
var csrftoken = getCookie('csrftoken');
var headers = new Headers();
headers.append('X-CSRFToken', csrftoken);
fetch('/api/upload', {
method: 'POST',
body: payload,
headers: headers,
credentials: 'include'
})
I came across a similar situation while working with DRF, the solution was appending .as_view()
method to the view in urls.py
.
I had the same error, in my case adding method_decorator helps:
from django.views.decorators.csrf import csrf_protect
from django.utils.decorators import method_decorator
method_decorator(csrf_protect)
def post(self, request):
...
This also occurs when you don’t set the form action.
For me, it was showing this error when the code was:
<form class="navbar-form form-inline my-2 my-lg-0" role="search" method="post">
When I corrected my code into this:
<form class="navbar-form form-inline my-2 my-lg-0" action="{% url 'someurl' %}" role="search" method="post">
my error disappeared.
If you’re using DRF, check if your urlpatterns are correct, maybe you forgot .as_view()
:
So that how mine code looked like:
urlpatterns += path('resource', ResourceView)
And that’s how it should like:
urlpatterns += path('resource', ResourceView.as_view())
If you are not using {% csrf_token %}
tag in the template you are rendering. Django won’t set the csrftoken cookie.
To force django to set the csrftoken cookie, add ensure_csrf_cookie decorator in you view.
from django.views.decorators.csrf import ensure_csrf_cookie
@ensure_csrf_cookie
def myview(request):
In my particular case, the problem is that I was using the Django rest_framework
and forgot to add the following decorators to my function:
from rest_framework.decorators import api_view, renderer_classes
@api_view(('POST',))
@renderer_classes((JSONRenderer,))
def handle_web_request(request):
...
Just want to point out my case here as someone might cross the same fields.
Forbidden (CSRF cookie not set.): /main/staff/products/validation/create
HTTP POST /main/staff/products/validation/create 403 [0.01, 127.0.0.1:55940]
This thing was driving me insane… So, by commenting CSRF middleware
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
)
it gave me
POST Method not allowed.
That was my hint, after all.
I was sure Post method was present.
Turns out my url_patterns
was leading to another view by a regex bug.
So no matter what I was doing in my view, @csrf_exempt @ensure_crsf_cookie
, looking for .as_view()
… I was looking at the wrong view.
So, if nothing works, make sure your are actually being sent to the right view.
You can get this error while deploing Django application with NO SSL.
If this is the case then putting an SSL reverse-proxy or SSL-configured Ingress in front of backend will solve the problem.
I get this error and change this:
<form method="post">
to this:
<form method="POST">
and it’s solved !
Just upper case post make the problem !
I have not any issue with this on 127.0.0.1, but when i use 192.168.x.x address this broke my forms.
In my case, setting CSRF_COOKIE_SECURE
to False
wasn’t enough but setting it to Null
/ not specifying the parameter worked.
In my case, the problem was that the path to the static files in nginx was incorrectly specified.
sudo tail -F /var/log/nginx/error.log
Check if there are errors in file paths.
I just tried this solution it work for me.
You have to set CSRF_USE_SESSIONS
to True
, basically the csrf token will be stored in a session
https://docs.djangoproject.com/en/4.1/ref/settings/#std-setting-CSRF_USE_SESSIONS
I have some problem for a while now, I’m experiencing CSRF Cookie not set. Please look at the code below:
views.py:
def deposit(request, account_num):
if request.method == 'POST':
account = get_object_or_404(account_info, acct_number=account_num)
form_ = AccountForm(request.POST or None, instance=account)
form = BalanceForm(request.POST)
info = str(account_info.objects.filter(acct_number=account_num))
inf = info.split()
if form.is_valid():
# cd=form.cleaned_data
now = datetime.datetime.now()
cmodel = form.save()
cmodel.acct_number = account_num
# RepresentsInt(cmodel.acct_number)
cmodel.bal_change = "%0.2f" % float(cmodel.bal_change)
cmodel.total_balance = "%0.2f" % (float(inf[1]) + float(cmodel.bal_change))
account.balance = "%0.2f" % float(cmodel.total_balance)
cmodel.total_balance = "%0.2f" % float(cmodel.total_balance)
# cmodel.bal_change=cmodel.bal_change
cmodel.issued = now.strftime("%m/%d/%y %I:%M:%S %p")
account.recent_change = cmodel.issued
cmodel.save()
account.save()
return HttpResponseRedirect("/history/" + account_num + "/")
else:
return render_to_response('history.html',
{'account_form': form},
context_instance=RequestContext(request))
Template file:
<form action="/deposit/{{ account_num }}/" method="post">
<table>
<tr>
{{ account_form.bal_change }}
<input type="submit" value="Deposit"/>
</tr>
{% csrf_token %}
</table>
</form>
I’n stuck, I already cleared the cookie, used other browser but still csrf cookie not set.
try to check if your have installed in the settings.py
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',)
In the template the data are formatted with the csrf_token:
<form>{% csrf_token %}
</form>
In your view are you using the csrf decorator??
from django.views.decorators.csrf import csrf_protect
@csrf_protect
def view(request, params):
....
Problem seems that you are not handling GET
requests appropriately or directly posting the data without first getting the form.
When you first access the page, client will send GET
request, in that case you should send html with appropriate form.
Later, user fills up the form and sends POST
request with form data.
Your view should be:
def deposit(request,account_num):
if request.method == 'POST':
form_=AccountForm(request.POST or None, instance=account)
if form.is_valid():
#handle form data
return HttpResponseRedirect("/history/" + account_num + "/")
else:
#handle when form not valid
else:
#handle when request is GET (or not POST)
form_=AccountForm(instance=account)
return render_to_response('history.html',
{'account_form': form},
context_instance=RequestContext(request))
Check that chrome’s cookies are set with default option for websites. Allow local data to be set (recommended).
Method 1:
from django.shortcuts import render_to_response
return render_to_response(
'history.html',
RequestContext(request, {
'account_form': form,
})
Method 2:
from django.shortcuts import render
return render(request, 'history.html', {
'account_form': form,
})
Because render_to_response
method may case some problem of response cookies.
This problem arose again recently due to a bug in Python itself.
http://bugs.python.org/issue22931
https://code.djangoproject.com/ticket/24280
Among the versions affected were 2.7.8 and 2.7.9.
The cookie was not read correctly if one of the values contained a [
character.
Updating Python (2.7.10) fixes the problem.
I have just met once, the solution is to empty the cookies.
And may be changed while debugging SECRET_KEY
related.
Clearing my browser’s cache fixed this issue for me. I had been switching between local development environments to do the django-blog-zinnia tutorial after working on another project when it happened. At first, I thought changing the order of INSTALLED_APPS
to match the tutorial had caused it, but I set these back and was unable to correct it until clearing the cache.
From This
You can solve it by adding the ensure_csrf_cookie decorator to your view
from django.views.decorators.csrf import ensure_csrf_cookie
@ensure_csrf_cookie
def yourView(request):
#...
if this method doesn’t work. you will try to comment csrf in middleware. and test again.
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def your_view(request):
if request.method == "POST":
# do something
return HttpResponse("Your response")
I was using Django 1.10 before.So I was facing this problem.
Now I downgraded it to Django 1.9 and it is working fine.
Make sure your django session backend is configured properly in settings.py. Then try this,
class CustomMiddleware(object):
def process_request(self,request:HttpRequest):
get_token(request)
Add this middleware in settings.py
under MIDDLEWARE_CLASSES
or MIDDLEWARE
depending on the django version
get_token – Returns the CSRF token required for a POST form. The token is an alphanumeric value. A new token is created if one is not already set.
If you’re using the HTML5 Fetch API to make POST requests as a logged in user and getting Forbidden (CSRF cookie not set.)
, it could be because by default fetch
does not include session cookies, resulting in Django thinking you’re a different user than the one who loaded the page.
You can include the session token by passing the option credentials: 'include'
to fetch:
var csrftoken = getCookie('csrftoken');
var headers = new Headers();
headers.append('X-CSRFToken', csrftoken);
fetch('/api/upload', {
method: 'POST',
body: payload,
headers: headers,
credentials: 'include'
})
I came across a similar situation while working with DRF, the solution was appending .as_view()
method to the view in urls.py
.
I had the same error, in my case adding method_decorator helps:
from django.views.decorators.csrf import csrf_protect
from django.utils.decorators import method_decorator
method_decorator(csrf_protect)
def post(self, request):
...
This also occurs when you don’t set the form action.
For me, it was showing this error when the code was:
<form class="navbar-form form-inline my-2 my-lg-0" role="search" method="post">
When I corrected my code into this:
<form class="navbar-form form-inline my-2 my-lg-0" action="{% url 'someurl' %}" role="search" method="post">
my error disappeared.
If you’re using DRF, check if your urlpatterns are correct, maybe you forgot .as_view()
:
So that how mine code looked like:
urlpatterns += path('resource', ResourceView)
And that’s how it should like:
urlpatterns += path('resource', ResourceView.as_view())
If you are not using {% csrf_token %}
tag in the template you are rendering. Django won’t set the csrftoken cookie.
To force django to set the csrftoken cookie, add ensure_csrf_cookie decorator in you view.
from django.views.decorators.csrf import ensure_csrf_cookie
@ensure_csrf_cookie
def myview(request):
In my particular case, the problem is that I was using the Django rest_framework
and forgot to add the following decorators to my function:
from rest_framework.decorators import api_view, renderer_classes
@api_view(('POST',))
@renderer_classes((JSONRenderer,))
def handle_web_request(request):
...
Just want to point out my case here as someone might cross the same fields.
Forbidden (CSRF cookie not set.): /main/staff/products/validation/create
HTTP POST /main/staff/products/validation/create 403 [0.01, 127.0.0.1:55940]
This thing was driving me insane… So, by commenting CSRF middleware
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
)
it gave me
POST Method not allowed.
That was my hint, after all.
I was sure Post method was present.
Turns out my url_patterns
was leading to another view by a regex bug.
So no matter what I was doing in my view, @csrf_exempt @ensure_crsf_cookie
, looking for .as_view()
… I was looking at the wrong view.
So, if nothing works, make sure your are actually being sent to the right view.
You can get this error while deploing Django application with NO SSL.
If this is the case then putting an SSL reverse-proxy or SSL-configured Ingress in front of backend will solve the problem.
I get this error and change this:
<form method="post">
to this:
<form method="POST">
and it’s solved !
Just upper case post make the problem !
I have not any issue with this on 127.0.0.1, but when i use 192.168.x.x address this broke my forms.
In my case, setting CSRF_COOKIE_SECURE
to False
wasn’t enough but setting it to Null
/ not specifying the parameter worked.
In my case, the problem was that the path to the static files in nginx was incorrectly specified.
sudo tail -F /var/log/nginx/error.log
Check if there are errors in file paths.
I just tried this solution it work for me.
You have to set CSRF_USE_SESSIONS
to True
, basically the csrf token will be stored in a session
https://docs.djangoproject.com/en/4.1/ref/settings/#std-setting-CSRF_USE_SESSIONS