Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a POST request (including CSRF token) using Django and AngularJS

Tags:

I'm trying to create a POST request using angular.js to this Django view.

class PostJSON4SlickGrid(View):     """     REST POST Interface for SlickGrid to update workpackages     """      def post(self, request, root_id, wp_id, **kwargs):         print "in PostJSON4SlickGrid"         print request.POST         return HttpResponse(status=200) 

Therefore I created this resource.

myModule.factory('gridData', function($resource) {     //define resource class     var root = {{ root.pk }};     return $resource('{% url getJSON4SlickGrid root.pk %}:wpID/', {wpID:'@id'},{             get: {method:'GET', params:{}, isArray:true},             update:{method:'POST'}     }); }); 

Calling the get method in a controller works fine. The url gets translated to http://127.0.0.1:8000/pm/rest/tree/1/.

function gridController($scope, gridData){     gridData.get(function(result) {         console.log(result);         $scope.treeData = result;         //broadcast that asynchronous xhr call finished         $scope.$broadcast('mySignal', {fake: 'Hello!'});       }); } 

While I m facing issues executing the update/POST method.

item.$update(); 

The URL gets translated to http://127.0.0.1:8000/pm/rest/tree/1/345, which is missing a trailing slash. This can be easily circumvented when not using a trailing slash in your URL definition.

url(r'^rest/tree/(?P<root_id>\d+)/(?P<wp_id>\d+)$', PostJSON4SlickGrid.as_view(), name='postJSON4SlickGrid'), 

instead of

url(r'^rest/tree/(?P<root_id>\d+)/(?P<wp_id>\d+)/$', PostJSON4SlickGrid.as_view(), name='postJSON4SlickGrid'), 

Using the workaround without the trailing slash I get now a 403 (Forbidden) status code, which is probably due to that I do not pass a CSRF token in the POST request. Therefore my question boils down to how I can pass the CSRF token into the POST request created by angular?

I know about this approach to pass the csrf token via the headers, but I m looking for a possibility to add the token to the body of the post request, as suggested here. Is it possible in angular to add data to the post request body?

As additional readings one can look at these discussions regarding resources, removed trailing slashes, and the limitations resources currently have: disc1 and disc2. In one of the discussions one of the authors recommended to currently not use resources, but use this approach instead.

like image 363
Thomas Kremmel Avatar asked Oct 10 '12 15:10

Thomas Kremmel


People also ask

How does Django generate CSRF token?

It generates a token on the server-side when rendering the page and makes sure to cross-check this token for any requests coming back in. If the incoming requests do not contain the token, they are not executed. Django makes this process seamless with the addition of a simple tag to the form generated.

How do I get CSRF token in Postman Django?

Instead, we can use Postman scripting feature to extract the token from the cookie and set it to an environment variable. In Test section of the postman, add these lines. var xsrfCookie = postman. getResponseCookie("csrftoken"); postman.

How do I add a CSRF token?

To use it, just include @csrf in your forms to include the token field.


1 Answers

I know this is more than 1 year old, but if someone stumbles upon the same issue, angular JS already has a CSRF cookie fetching mechanism (versions of AngularJS starting at 1.1.5), and you just have to tell angular what is the name of the cookie that django uses, and also the HTTP header that it should use to communicate with the server.

Use module configuration for that:

var app = angular.module('yourApp'); app.config(['$httpProvider', function($httpProvider) {     $httpProvider.defaults.xsrfCookieName = 'csrftoken';     $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken'; }]); 

Now every request will have the correct django CSRF token. In my opinion this is much more correct than manually placing the token on every request, because it uses built-in systems from both frameworks (django and angularJS).

like image 119
Anoyz Avatar answered Sep 28 '22 03:09

Anoyz