1

I am trying to finish a geo Django tutorial which is quite old (1.3). Till now I was doing great but I am stucked with a specific error.

I am trying to build the functionality in which I save some data to the table in db. This is my view:

# Import django modules
from django.shortcuts import render_to_response
from django.template.loader import render_to_string
from django.http import HttpResponse
import simplejson
from waypoints.models import Waypoint

def save(request):
'Save waypoints'
for waypointString in request.POST.get('waypointsPayload', '').splitlines():
    waypointID, waypointX, waypointY = waypointString.split()
    waypoint = Waypoint.objects.get(id=int(waypointID))
    waypoint.geometry.set_x(float(waypointX))
    waypoint.geometry.set_y(float(waypointY))
    waypoint.save()
return HttpResponse(simplejson.dumps(dict(isOk=1)),    mimetype='application/json')

When I select the Save button I get an error (in firebug):403 Forbidden Now I know that is related with:

<h1>Forbidden <span>(403)</span></h1>
<p>CSRF verification failed. Request aborted.</p>

But I have no idea how to fix it.

Moe Far
  • 2,742
  • 2
  • 23
  • 41
user1919
  • 3,818
  • 17
  • 62
  • 97
  • Either add `{% csrf_token %}` after your HTML `
    ` tag (safe) or add @csrf_exempt before `def save(request):` (unsafe)
    – Selcuk Feb 13 '16 at 16:07
  • @Selcuk thank you very much for the answer. Can you please be a bit more specific. Right now I don't have any form tag. Just: Should I add it insed the input? – user1919 Feb 13 '16 at 16:11
  • Possible duplicate of [Django - CSRF verification failed](http://stackoverflow.com/questions/4547639/django-csrf-verification-failed) – Selcuk Feb 13 '16 at 16:11
  • 1
    How do you POST without a form tag? Through Javascript? – Selcuk Feb 13 '16 at 16:11
  • Yes. Using jquery. Its just a tutorial which I try to finish so I get a first idea of geodjango! – user1919 Feb 13 '16 at 16:12

2 Answers2

1

As @Selcuk suggested, using the Django decorator csrf_exempt on your view function should fix this. However, take into consideration that it won't protect your request against CSRF attacks.
You can read more about how it works here.

# Import django modules
from django.http import HttpResponse
# import csrf_exempt
from django.views.decorators.csrf import csrf_exempt
# Import system modules
import simplejson
# Import custom modules
from googlemaps.waypoints.models import Waypoint

@csrf_exempt 
def save(request):
    'Save waypoints'
    for waypointString in request.POST.get('waypointsPayload', '').splitlines():
        waypointID, waypointX, waypointY = waypointString.split()
        waypoint = Waypoint.objects.get(id=int(waypointID))
        waypoint.geometry.set_x(float(waypointX))
        waypoint.geometry.set_y(float(waypointY))
        waypoint.save()
    return HttpResponse(simplejson.dumps(dict(isOk=1)), mimetype='application/json')
Forge
  • 6,538
  • 6
  • 44
  • 64
  • Don't use this unless you have a very good reason. CSRF is a security measure that is there to avoid other people being able to post data on your behalf. See my answer for the secure solution. – Emil Stenström Feb 13 '16 at 16:43
1

The correct way to solve this is to add a {% csrf_token %} to your Django template. You need a form tag for this to work, and you should have one no matter what. Otherwise, how does the browser know where to send your data?

<form action="" method="post">
    {% csrf_token %}
    <input id=saveWaypoints type=button value=Save disabled=disabled>
</form

The Django documentation has lots of good information on how CSRF works and why it's important: https://docs.djangoproject.com/en/1.9/ref/csrf/#how-to-use-it

Emil Stenström
  • 13,329
  • 8
  • 53
  • 75