J'essaie de créer une demande POST en utilisant angular.js à cette vue Django.
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)
J'ai donc créé cette ressource.
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'}
});
});
L'appel de la méthode get dans un contrôleur fonctionne bien. L'URL est traduit en 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!'});
});
}
Pendant que je suis confronté à des problèmes d’exécution de la méthode update/POST.
item.$update();
L'URL est traduite en http://127.0.0.1:8000/pm/rest/tree/1/345
, sans barre oblique. Cela peut être facilement contourné lorsque vous n'utilisez pas de barre oblique finale dans votre définition d'URL.
url(r'^rest/tree/(?P<root_id>\d+)/(?P<wp_id>\d+)$', PostJSON4SlickGrid.as_view(), name='postJSON4SlickGrid'),
au lieu de
url(r'^rest/tree/(?P<root_id>\d+)/(?P<wp_id>\d+)/$', PostJSON4SlickGrid.as_view(), name='postJSON4SlickGrid'),
En utilisant la solution de contournement sans la barre oblique finale, je reçois maintenant un code de statut 403 (interdit), ce qui est probablement dû à cela. Je ne passe pas de jeton CSRF dans la requête POST. Par conséquent, ma question se résume à la façon dont je peux passer le jeton CSRF dans la demande POST créée par angular?
Je sais que cette approche permet de passer le jeton csrf via les en-têtes, mais je cherche une possibilité pour ajouter le jeton au corps de la requête post, comme suggéré ici . Est-il possible, en mode angulaire, d'ajouter des données au corps de la demande de publication?
Comme lectures supplémentaires, on peut examiner ces discussions concernant les ressources, les barres obliques de fin supprimées et les limitations actuelles des ressources: disc1 et disc2 . Dans l'une des discussions, l'un des auteurs a recommandé de n'utilisez pas de ressources, mais utilisez this à la place.
Tu ne peux pas faire un appel comme ça:
$http({
method: 'POST',
url: url,
data: xsrf,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
La data
peut être celle que vous souhaitez transmettre, puis ajoutez simplement &{{csrf_token}}
à cela.
Dans votre ressource params:{}
, essayez d’ajouter csrfmiddlewaretoken:{{csrf_token}}
dans la variable params
.
Modifier:
Vous pouvez transmettre des données au corps de la demande en tant que
item.$update({csrfmiddlewaretoken:{{csrf_token}}})
et aux en-têtes comme
var csrf = '{{ csrf_token }}';
update:{method:'POST', headers: {'X-CSRFToken' : csrf }}
C'est un sans-papiers issue
Je sais que cela fait plus d'un an, mais si quelqu'un tombe sur le même problème, JS angular dispose déjà d'un mécanisme d'extraction de cookies CSRF (versions d'AngularJS commençant à 1.1.5) et il vous suffit de dire à Angular quel est le nom. du cookie utilisé par Django, ainsi que l’en-tête HTTP à utiliser pour communiquer avec le serveur.
Utilisez la configuration du module pour cela:
var app = angular.module('yourApp');
app.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}]);
Désormais, chaque requête aura le bon jeton Django CSRF. À mon avis, cela est beaucoup plus correct que de placer manuellement le jeton sur chaque demande, car il utilise des systèmes intégrés issus des deux frameworks (Django et angularJS).
Dans la version récente d'angularjs, la solution proposée ne fonctionne pas. J'ai donc essayé ce qui suit
Commencez par ajouter la balise Django {% csrf_token%} dans le balisage.
Ajouter un inspecteur $ http dans votre fichier de configuration d'application
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;
}};
});
il va ajouter le X-CSRFToken dans toute demande angulaire
Enfin, vous devez ajouter le middleware Django "Django.middleware.csrf.CsrfViewMiddleware '" Il résoudra le problème de CSRF.
J'utilise ceci:
Dans la vue Django:
@csrf_protect
def index(request):
#Set cstf-token cookie for rendered template
return render_to_response('index.html', RequestContext(request))
Dans 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));
Pour envoyer une demande correcte, vous devez convertir l'objet en param-form:
$http.post('/items/add/', $.param({name: 'Foo'}));//Here $ is jQuery
var app = angular.module('angularFoo', ....
app.config(["$httpProvider", function(provider) {
provider.defaults.headers.common['X-CSRFToken'] = '<<csrftoken value from template or cookie>>';
}])