How to make a POST simple JSON using Django REST Framework? CSRF token missing or incorrect

user798719 picture user798719 · Jul 6, 2013 · Viewed 73.9k times · Source

Would appreciate someone showing me how to make a simple POST request using JSON with Django REST framework. I do not see any examples of this in the tutorial anywhere?

Here is my Role model object that I'd like to POST. This will be a brand new Role that I'd like to add to the database but I'm getting a 500 error.

{
    "name": "Manager", 
    "description": "someone who manages"
}

Here is my curl request at a bash terminal prompt:

curl -X POST -H "Content-Type: application/json" -d '[
{
    "name": "Manager", 
    "description": "someone who manages"
}]'


http://localhost:8000/lakesShoreProperties/role

The URL

http://localhost:8000/lakesShoreProperties/roles

DOES work with a GET request, and I can pull down all the roles in the database, but I can not seem to create any new Roles. I have no permissions set. I'm using a standard view in views.py

class RoleDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Role.objects.all()
    serializer_class = RoleSerializer
    format = None

class RoleList(generics.ListCreateAPIView): 
        queryset = Role.objects.all()
        serializer_class = RoleSerializer
        format = None

And in my urls.py for this app, the relevant url - view mappings are correct:

url(r'^roles/$', views.RoleList.as_view()),
url(r'^role/(?P<pk>[0-9]+)/$', views.RoleDetail.as_view()),

Error message is:

{
    "detail": "CSRF Failed: CSRF token missing or incorrect."
}

What is going on here and what is the fix for this? Is localhost a cross site request? I have added @csrf_exempt to RoleDetail and RoleList but it doesn't seem to change anything. Can this decorator even be added to a class, or does it have to be added to a method? Adding the @csrf_exempt decorate, my error becomes:

Request Method: POST
Request URL:    http://127.0.0.1:8000/lakeshoreProperties/roles/
Django Version: 1.5.1
Exception Type: AttributeError
Exception Value:    
'function' object has no attribute 'as_view'

Then I disabled CSRF throughtout the entire app, and I now get this message:

{"non_field_errors": ["Invalid data"]} when my JSON object I know is valid json. It's a non-field error, but I'm stuck right here.

Well, it turns out that my json was not valid?

{
    "name": "admin", 
    "description": "someone who administrates"
}

vs

[
    {
        "name": "admin",
        "description": "someone who administrates"
    }
]

Having the enclosing brackets [], causes the POST request to fail. But using the jsonlint.com validator, both of my json objects validate.

Update: The issue was with sending the POST with PostMan, not in the backend. See https://stackoverflow.com/a/17508420/203312

Answer

Terry Lam picture Terry Lam · Oct 13, 2013

CSRF is exempted by default in Django REST Framework. Therefore, curl POST request works fine. POSTMAN request call returned CSRF incorrect because POSTMAN included csrf token if it is found in Cookies. You can solve this by cleaning up Cookies.