How to make a Django-Rest-Framework API that takes

2019-01-29 00:23发布

问题:

I'm building a Django application with Django-Rest-Framework APIs. I have built an API endpoint as follows. I want to be able to POST data from my browser. I want to retrieve an object model from my Database that has the matching primary as given in the URL. And I want to operate on that retrieved object based on the data posted by the browser. If I could just grab the posted data from with my ViewSet, I would be done. But I don't know how to get to execute that viewset's update() function when I do a POST.

From my urls.py file:

router.register(r'replyComment', views.ReplyComment, base_name="replyComment")

From my views.py file:

class ReplyComment(viewsets.ViewSet):
    def update(self,request,pk=None):
        try: 
            origComment = Comment.objects.get(pk=pk)
            # Do something here that modifies the state of origComment and saves it.
            return Response(
                json.dumps(True), 
                status=status.HTTP_200_OK,
            )
        except Exception as exception:
            logger.error(exception)
            return Response(status=status.HTTP_400_BAD_REQUEST)

I'm using the Advanced Rest Client (ARC) tool in my Chrome browser. When I point the ARC tool to http://127.0.0.1:3001/api/replyComment/2/ using the POST method, I get the error:

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

See the screenshot here. It seems like I'm doing something wrong here with my POST. Can someone please advise how to do this properly? How can I get around my CSRF issue? I'm a newbie to Django Rest Frameworks. So if you can provide clear details, it would be most appreciated. Please let me know what changes I need to make to ensure my POST works as I intend it to? I need a bit more help than simply referring me to the manual. (I tried that but still couldn't make it work)

回答1:

CSRF Tokens are required in Django to protect against CSRF(Cross Site Request Forgery). For methods that writes something (POST, PUT, DELETE etc), you need to include a CSRF token with your request so that Django knows the request came from your own site.

You can read more about in Django-rest-framework documentation. And as it says in the doc, you can find how to include the CSRF token in the HTTP Header in Django documentation.



回答2:

Well. other answers are correct. but i guess your problem is that you don't know how to use these answers.

here is an example. lets say i want to send a field name with jquery ajax function over PUT method(updating name on a model).

first we should get the csrf-token from cookies server send us. this function from django documentation does the job(getting some value from cookie):

// using jQuery
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;
}

when we send put request, we will send the csrf token in request header:

var jqxhr = $.ajax('/rest/gallery/5/', {
                    method: 'PUT',
                    type: 'PUT',
                    beforeSend: function (xhr) {
                         xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
                    },
                    data: {
                        name: 'salam dadash'
                    }
                });
                jqxhr.done(function (result) {
                    console.log(result);
                });

note that in beforeSend i set the X-CSRFToken so csrf-token is sent in request header.

you should change url and data of course.



回答3:

See the Headers field above the payload?

Try adding this:

{"X-CSRFToken": "gZvnzSFeGp7h68WjCzmFky6wMkiJZXDU"}

I viewed the screen shot and squinted trying to read out the CSRF token you have set on your server. So it could be wrong, double check it against your settings.py file. Bibhas is correct, but this is how you accomplish a POST using ARC in your browser.