我正在尝试使用angular.js为此Django视图创建一个POST请求。
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)
因此我创建了这个资源。
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'}
});
});
在控制器中调用 get 方法可以正常工作。该网址已转换为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!'});
});
}
当我遇到执行更新/ POST方法的问题时。
item.$update();
网址被转换为http://127.0.0.1:8000/pm/rest/tree/1/345
,缺少尾部斜杠。在URL定义中不使用尾部斜杠时,可以轻松避免这种情况。
url(r'^rest/tree/(?P<root_id>\d+)/(?P<wp_id>\d+)$', PostJSON4SlickGrid.as_view(), name='postJSON4SlickGrid'),
而不是
url(r'^rest/tree/(?P<root_id>\d+)/(?P<wp_id>\d+)/$', PostJSON4SlickGrid.as_view(), name='postJSON4SlickGrid'),
使用没有尾部斜杠的变通方法我现在得到403(禁止)状态代码,这可能是因为我没有在POST请求中传递CSRF标记。因此,我的问题归结为我如何将CSRF令牌传递给angular?
创建的POST请求我知道通过标头传递csrf令牌的this方法,但我正在寻找一种可能将令牌添加到帖子请求的正文,如建议{ {3}}。是否可以在角度中将数据添加到帖子请求主体?
作为附加读物,您可以查看有关资源,删除的尾部斜杠以及当前具有的限制资源的这些讨论:here和disc1。 在其中一个讨论中,作者之一建议当前不使用资源,而是使用disc2方法。
答案 0 :(得分:39)
我知道这已经超过1年了,但如果有人遇到同样的问题,角度JS已经有了一个CSRF cookie获取机制(AngularJS的版本从1.1.5开始),你只需告诉angular是什么是django使用的cookie的名称,以及它应该用于与服务器通信的HTTP头。
使用模块配置:
var app = angular.module('yourApp');
app.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}]);
现在每个请求都有正确的django CSRF令牌。在我看来,这比在每个请求上手动放置令牌要正确得多,因为它使用来自两个框架(django和angularJS)的内置系统。
答案 1 :(得分:7)
你不能这样打电话:
$http({
method: 'POST',
url: url,
data: xsrf,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
data
可以是您希望传递的任何内容,然后只需将&{{csrf_token}}
附加到其中。
在您的资源params:{}
中,尝试在csrfmiddlewaretoken:{{csrf_token}}
params
编辑:
您可以将数据作为
传递给请求正文item.$update({csrfmiddlewaretoken:{{csrf_token}}})
和标题为
var csrf = '{{ csrf_token }}';
update:{method:'POST', headers: {'X-CSRFToken' : csrf }}
这是一张未记录的issue
答案 2 :(得分:1)
在最近的angularjs版本中,解决方案无效。所以我尝试了以下
首先在标记中添加django标记{%csrf_token%}。
在您的应用配置文件中添加$ http检查器
angular.module('myApp').config(function ( $httpProvider) {
$httpProvider.interceptors.push('myHttpRequestInterceptor');
});
angular.module("myApp").factory('myHttpRequestInterceptor', function ( ) {
return {
config.headers = {
'X-CSRFToken': $('input[name=csrfmiddlewaretoken]').val() }
}
return config;
}};
});
它将在所有角度请求中添加X-CSRFToken
最后你需要添加Django中间件“django.middleware.csrf.CsrfViewMiddleware” 它将解决CSRF问题
答案 3 :(得分:0)
var app = angular.module('angularFoo', ....
app.config(["$httpProvider", function(provider) {
provider.defaults.headers.common['X-CSRFToken'] = '<<csrftoken value from template or cookie>>';
}])
答案 4 :(得分:0)
我用这个:
在Django视图中:
@csrf_protect
def index(request):
#Set cstf-token cookie for rendered template
return render_to_response('index.html', RequestContext(request))
在App.js中:
(function(A) {
"use strict";
A.module('DesktopApplication', 'ngCookies' ]).config(function($interpolateProvider, $resourceProvider) {
//I use {$ and $} as Angular directives
$interpolateProvider.startSymbol('{$');
$interpolateProvider.endSymbol('$}');
//Without this Django not processed urls without trailing slash
$resourceProvider.defaults.stripTrailingSlashes = false;
}).run(function($http, $cookies) {
//Set csrf-kookie for every request
$http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;
$http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
});
}(this.angular));
要发送正确的请求,您必须将对象转换为参数格式:
$http.post('/items/add/', $.param({name: 'Foo'}));//Here $ is jQuery