Django 1.5 CSRF Ajax
ajax, django, jquery, python
Solution
If i were you, i would remove that AJAX below the "// Boilerplate for handling CSRF, from Django's website" comment and replace "the actual ajax" with this:
// the actual Ajax
$("#submitSquats").click(function() {
var form = $(this).parent();
$.post(
"submitWorkout1", //url
form.serialize(), //data
function() { //success method
$('#squats').html('<span>Success</span>');
}
);
return false;
});
If you are getting a 403 error, it must be because you are not sending the csrf token... This is easily done with `form.serialize()`, together with all form data....
Problem
I'm trying to create a web app that makes Ajax calls when certain buttons are clicked, updating data in my models and displaying the updated data. Here is my template: ``` <html> <head> <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script> <script src="{{ STATIC_URL }}/workout1.js"></script> </head> <body> <span id="squats">Squats: {{ user.weekOne.squats }} done.<br/></span> <span id="lunges">Lunges: {{ user.weekOne.lunges }} done.<br /></span> <span id="stairDays">Stair Days: {{ user.weekOne.stairDaysCount }}<br/></span> <span id="skipStairs">Skip Stairs: {{ user.weekOne.skipStairs }}<br /></span> <form> {% csrf_token %} <input type="text" name="squats" id="squatsVal" value="Squats" /> <input type="submit" id="submitSquats" value="Add Squats"/><br /> </form> <form> <input type="text" name="lunges" value="Lunges" /> <input type="submit" value="Add Lunges" /><br /> </form> <form> <input type="submit" value="Stairs skipped."><br /> </form> </body> </html> ``` I use Django's suggested code for dealing with Ajax and CSRF. Here is my resultant jQuery: $(document).ready(function() { ``` // Boilerplate for handling CSRF, from Django's website 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; }; var csrftoken = getCookie('csrftoken'); $.ajaxSetup({ crossDomain: false, // obviates need for sameOrigin test beforeSend: function(xhr, settings) { if (!csrfSafeMethod(settings.type)) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } }); // the actual Ajax $("#submitSquats").click(function() { var exercise = "squats"; var amount = $('#squats').val(); var data = {'exercise': exercise, 'amount': amount}; $.ajax({ type:"POST", url:"submitWorkout1", data: data, success: function() { $('#squats').html('<span>Success</span>'); } }); return false; }); ``` }); Finally, here is the view that handles the incoming Ajax request and returns a response for the Ajax to work with: ``` def submitWorkout1(request): exercise = request.POST['exercise'] amount = request.POST['amount'] user = UserProfile.objects.get(user=request.user) exercise, amount = user.WeekOne.updateExercise(exercise, amount) return HttpResponse(simplejson.dumps({'result': 'success', exercise: amount})) ``` Unfortunately, when I try to click on the Submit Squats button and run the jQuery, I get a `CSRF Token Missing or Incorrect` error message. Moreover, if I use a @csrf_exempt identifier on top of my view for testing purposes, I get this error: ``` "Key 'exercise' not found in <QueryDict: {u'undefined': [u'', u'']}>" ``` So even if I were to fix the CSRF problem, it appears there is something else wrong with my Ajax code. But I want to fix both problems. Help! Updated code (see catherine's post below): HTML: ``` <body> <span id="squats">Squats: {{ user.weekOne.squats }} done.<br/></span> <span id="lunges">Lunges: {{ user.weekOne.lunges }} done.<br /></span> <span id="stairDays">Stair Days: {{ user.weekOne.stairDaysCount }}<br/></span> <span id="skipStairs">Skip Stairs: {{ user.weekOne.skipStairs }}<br /></span> <form method="POST" action="{% url workout_game_app.views.submitWorkout1 %}"> {% csrf_token %} <input type="text" name="squats" id="squatsVal" value="Squats" /> <input type="submit" id="submitSquats" value="Add Squats"/><br /> </form> </body> ``` jQuery: ``` $(document).ready(function() { $("#submitSquats").click(function() { var exercise = "squats"; var amount = $('#squats').val(); $.ajax({ type:"POST", url:"/workout_game_app/workouts/submitWorkout1/", data: {'exercise': exercise, 'amount:': amount, 'csrfmiddlewaretoken': '{{csrf_token}}'}, contentType: "application/json;charset=utf-8", dataType: "json", success: function() { $('#squats').html('<span>Success</span>'); } }); return false; }); }); ``` view: ``` def submitWorkout1(request): if request.method == 'POST': exercise = request.POST['exercise'] amount = request.POST['amount'] user = UserProfile.objects.get(user=request.user) exercise, amount = user.WeekOne.updateExercise(exercise, amount) data = simplejson.dumps({ 'result': 'success', 'exercise': exercise, 'amount': amount }, indent=4) return HttpResponse(data, mimetype="application/javascript") ``` URL: ``` urlpatterns = patterns('', url(r'^$', 'workout_game_app.views.index'), url(r'^signup$/', 'workout_game_app.views.signup'), url(r'^login$/', 'workout_game_app.views.login_view'), url(r'^logout/$', 'workout_game_app.views.logout_view'), url(r'^workouts/workout1/$', 'workout_game_app.views.workout1'), url(r'^workouts/submitWorkout1/$', 'workout_game_app.views.submitWorkout1'), ```