4

AoA I am new to Django, I am trying to get data from POST, but getting error CSRF cookie not set, I tried alot to find the solution on google and stackoverflow via google too, but failed

here is the code

views.py

    from django.http import HttpResponse
    from django.template.loader import get_template
    from django.template import Context
    from django.template import RequestContext
    from django.core.context_processors import csrf
    from django.shortcuts import render_to_response

def search_Post(request):
    if request.method == 'POST':
            c = {}
        c.update(csrf(request))
        # ... view code here
                return render_to_response("search.html", c)

def search_Page(request):
    name='Awais you have visited my website :P'
    t = get_template('search.html')
    html = t.render(Context({'name':name}))
    return HttpResponse(html)

HTML File

<p>
          {{ name }}
            <form method="POST" action="/save/">
              {% csrf_token %}
              <textarea name="content" rows="20" cols="60">{{content}}</textarea><br>
              <input type="submit" value="Save Page"/>
            </form>
       <div>  Cant figure out any solution! :( </div>

 </p>

url.py

 url(r'^home/$', 'contacts.views.home_Page'),
 url(r'^save/$', 'contacts.views.search_Post'),
 url(r'^edit/$', 'contacts.views.edit_Page'),
 url(r'^search/$', 'contacts.views.search_Page'),

settings.py

TEMPLATE_CONTEXT_PROCESSORS = (
    'django.core.context_processors.csrf',
    'django.contrib.auth.context_processors.auth',
    'django.core.context_processors.debug',
    'django.core.context_processors.i18n',
    'django.core.context_processors.media',
    'django.core.context_processors.static',
    'django.core.context_processors.request',
    'django.contrib.messages.context_processors.messages'
)

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    # Uncomment the next line for simple clickjacking protection:
    # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
Saad Abdullah
  • 2,252
  • 3
  • 29
  • 42

5 Answers5

9

I had the same problem, and resolved 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):
     #...

It will set csrftoken in browser cookie and you can make ajax like this

function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie != '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) == (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}
function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
    crossDomain: false, // obviates need for sameOrigin test
    beforeSend: function(xhr, settings) {
        if (!csrfSafeMethod(settings.type)) {
            xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
        }
    }
});
$.ajax({
        url: url,
        type: type,
        async: async,
        data: data,
        error: function (e) {},
        success: function (data) {
                returnFunction(data);
            }
    });
Mathieu Dhondt
  • 8,405
  • 5
  • 37
  • 58
Yoganand
  • 300
  • 3
  • 15
5

You use both means to pass CSRF token to template processor

c = {}
c.update(csrf(request))

and RequestContext, while one is enough, see docs. But you use it wrong place, for serving 'POST' request. Those requests are normally sent by your browser when it fills up a form and want to get results.

Your browser renders home.html sending GET request to a server, which is served by

t = get_template('home.html')
html = t.render(ResponseContext({'name':name}))
return HttpResponse(html)

part of your code. And there you do not use any mean to pass csrf token. So when your template processor get_template().render() is invoked, is has no token in its context, so simply ignores {% csrf_token %} code in template. So you have to either use RequestContext in t.render(...) part of view, or pass you c dict there.

You can check it inspecting generated form in a browser window.

UPDATE

In seetings.py add a comma after 'django.core.context_processors.csrf', the way it is now, it just contcatenates strings.

Should be:

TEMPLATE_CONTEXT_PROCESSORS = (
    'django.core.context_processors.csrf',
    'django.contrib.auth.context_processors.auth',
    'django.core.context_processors.debug',
Daniel Lyons
  • 22,421
  • 2
  • 50
  • 77
alko
  • 46,136
  • 12
  • 94
  • 102
  • do you see csrf token in generated html? – alko Oct 25 '13 at 21:00
  • what is this ResponseContext? – Saad Abdullah Oct 25 '13 at 21:04
  • Updated by question with urls.py and used one request( you taught me alot) and render the page..still csrf field is missing in search.html and get the verification failed error on clicking the POST button...I have made another method for this...check above... and why sould I add colon? 'django.core.context_processors.csrf':, it gives me alist of error when I runserver – Saad Abdullah Oct 25 '13 at 21:36
  • problem is solved :) very thanks for your help... i was using this for GET t = get_template('home.html') c = RequestContext(request, {'name':name}) and for your mentioned code in POST...which gave me errors, Replacing the get_template with c = {'name': name} c.update(csrf(request)) solved the problem :) Once again thanks :) – Saad Abdullah Oct 25 '13 at 22:08
  • 2
    In that case I suggest you mark question answered, either choosing from existing answers or if you not feel it appropriate, adding your own. – alko Oct 26 '13 at 11:30
1

It seems that You have forgot to pass request to render

Django comes with a special Context class, django.template.RequestContext, that acts slightly differently than the normal django.template.Context. The first difference is that it takes an HttpRequest as its first argument. For example:

In addition to these, RequestContext always uses django.core.context_processors.csrf. This is a security related context processor required by the admin and other contrib apps, and, in case of accidental misconfiguration, it is deliberately hardcoded in and cannot be turned off by the TEMPLATE_CONTEXT_PROCESSORS setting.

So What You need is following

t = get_template('home.html')
c = RequestContext(request, {'name':name})
return HttpResponse(t.render(c))

If You wold like You can check django dock here https://docs.djangoproject.com/en/dev/ref/templates/api/#django.template.RequestContext

Community
  • 1
  • 1
oleg
  • 4,082
  • 16
  • 16
1

Start from fixing your HTML (You forgot =):

<form method="POST" action="/search/save">
{% csrf_token %}
<textarea name="content" rows="20" cols="60">{{content}}</textarea><br>
<input type="submit" value="Save Page"/>
</form>

Also:

def home_Page(request):
    #if request.method == 'GET':
    name='Awais you have visited my website :P'
    if request.method == 'POST':
        #name = request.POST.get('content')
        return render_to_response("search.html", {}, context_instance=RequestContext(request))

    return render_to_response("home.html", {'name':name}, context_instance=RequestContext(request))
Dmitry Demidenko
  • 3,427
  • 1
  • 22
  • 22
-4

Try using the exact IP address with the port number instead of the DNS... Like instead of localhost use 127.0.0.1 along with the port number.

impiyush
  • 754
  • 1
  • 8
  • 17
  • This has nothing to do with the question. In addition to that, you have used the term DNS incorrectly. It does not make any sense to use the IP address instead of the hostname. – Alexandre V. Nov 19 '17 at 19:50