rest_framework - rest framework django 2
Cómo crear una solicitud POST(incluido token CSRF) usando Django y AngularJS (5)
En la versión anglosajona reciente, la solución de dar no funciona. Así que intenté lo siguiente
Primero agregue la etiqueta django {% csrf_token%} en el marcado.
Agregue un inspector $ http en el archivo de configuración de su aplicación
angular.module(''myApp'').config(function ( $httpProvider) {
$httpProvider.interceptors.push(''myHttpRequestInterceptor'');
});
- Luego defina que myHttpRequestInterceptor
angular.module("myApp").factory(''myHttpRequestInterceptor'', function ( ) {
return {
config.headers = {
''X-CSRFToken'': $(''input[name=csrfmiddlewaretoken]'').val() }
}
return config;
}};
});
agregará el X-CSRFToken en todas las solicitudes angulares
Y, por último, debe agregar el middleware de Django "django.middleware.csrf.CsrfViewMiddleware" "Solucionará el problema de CSRF
Estoy intentando crear una solicitud POST usando angular.js a esta vista de 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)
Por lo tanto, creé este recurso.
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''}
});
});
Llamar al método get en un controlador funciona bien. La URL se traduce a 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!''});
});
}
Mientras estoy enfrentando problemas al ejecutar el método de actualización / POST.
item.$update();
La URL se traduce a http://127.0.0.1:8000/pm/rest/tree/1/345
, que le falta una barra diagonal. Esto se puede eludir fácilmente cuando no se utiliza una barra inclinada en la definición de su URL.
url(r''^rest/tree/(?P<root_id>/d+)/(?P<wp_id>/d+)$'', PostJSON4SlickGrid.as_view(), name=''postJSON4SlickGrid''),
en lugar de
url(r''^rest/tree/(?P<root_id>/d+)/(?P<wp_id>/d+)/$'', PostJSON4SlickGrid.as_view(), name=''postJSON4SlickGrid''),
Al usar la solución alternativa sin la barra al final, obtengo un código de estado 403 (Prohibido), que probablemente se deba a que no CSRF un token CSRF en la solicitud POST. Por lo tanto, mi pregunta se reduce a cómo puedo pasar el token CSRF en la solicitud POST creada por angular.
Sé acerca de this enfoque para pasar el token csrf a través de los encabezados, pero estoy buscando la posibilidad de agregar el token al cuerpo de la solicitud posterior , como se sugiere here . ¿Es posible en angular agregar datos al cuerpo de solicitud de publicación?
Como lecturas adicionales, se pueden ver estas discusiones con respecto a los recursos, barras diagonales eliminadas y las limitaciones que actualmente tienen los recursos: disc1 y disc2 . En una de las discusiones, uno de los autores recomendó que actualmente no use recursos, pero use disc2 enfoque en su lugar.
No puedes hacer una llamada como esta:
$http({
method: ''POST'',
url: url,
data: xsrf,
headers: {''Content-Type'': ''application/x-www-form-urlencoded''}
})
Los data
pueden ser lo que quieras pasar y luego anexar &{{csrf_token}}
a eso.
En sus params:{}
recursos params:{}
, intente agregar csrfmiddlewaretoken:{{csrf_token}}
dentro de los params
Editar:
Puede pasar datos al cuerpo de la solicitud como
item.$update({csrfmiddlewaretoken:{{csrf_token}}})
y a encabezados como
var csrf = ''{{ csrf_token }}'';
update:{method:''POST'', headers: {''X-CSRFToken'' : csrf }}
Es un issue no documentado
Sé que esto tiene más de 1 año, pero si alguien tropieza con el mismo problema, angular JS ya tiene un mecanismo de búsqueda de cookies CSRF (versiones de AngularJS comenzando en 1.1.5), y solo tiene que decir angular cuál es el nombre de la cookie que utiliza django, y también el encabezado HTTP que debe usar para comunicarse con el servidor.
Use la configuración del módulo para eso:
var app = angular.module(''yourApp'');
app.config([''$httpProvider'', function($httpProvider) {
$httpProvider.defaults.xsrfCookieName = ''csrftoken'';
$httpProvider.defaults.xsrfHeaderName = ''X-CSRFToken'';
}]);
Ahora, cada solicitud tendrá el token django CSRF correcto. En mi opinión, esto es mucho más correcto que colocar manualmente el token en cada solicitud, porque usa sistemas integrados de ambos frameworks (django y angularJS).
Yo uso esto:
En la vista de Django:
@csrf_protect
def index(request):
#Set cstf-token cookie for rendered template
return render_to_response(''index.html'', RequestContext(request))
En 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));
Para enviar la solicitud correcta, debe convertir el objeto a 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>>'';
}])