使用 angular 向 django-rest 发送 DELETE 请求被解释为 OPTIONS
Posted
技术标签:
【中文标题】使用 angular 向 django-rest 发送 DELETE 请求被解释为 OPTIONS【英文标题】:Sending a DELETE request to django-rest with angular is interpreted as OPTIONS 【发布时间】:2013-11-20 05:31:04 【问题描述】:我尝试使用 django-rest 和 angularjs 构建的 rest API,但我遇到了问题。 当我发送 DELETE 请求时,django-rest 看到 OPTIONS。
这就是我所做的:
我的 Django views.py
@api_view(['GET', 'PUT', 'DELETE'])
def node_detail(request, pk):
"""
Retrieve, update or delete a node.
"""
try:
node = Node.objects.get(pk=pk)
except Node.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = NodeSerializer(node)
return Response(serializer.data)
elif request.method == 'PUT':
data = JSONParser().parse(request)
serializer = NodeSerializer(node, data=data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
node.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
我已经添加了带有 django-cors-headers 的 CORS,并且所有的 Origin 都被接受(CORS_ORIGIN_ALLOW_ALL = True)
我有一个角度服务来管理这个 $resource
angular.module('akilio.nodes.services', ['ngResource'])
.factory('NodeServices', function($resource)
return $resource('http://127.0.0.1:8000/nodes/:nodeId/', nodeId: '@nodeId');
);
现在,使用 ng-click="deleteNode()" 的按钮,我称之为控制器
controller('DetailCtrl', ['$scope', '$routeParams', 'NodeServices', function($scope, $routeParams, NodeServices)
$scope.node = NodeServices.get(nodeId: $routeParams.pk);
$scope.deleteNode = function()
$scope.node.$delete(function()
console.log('ok');
, function()
console.log('nok');
);
;
]);
console.log() 每次都返回“nok”,在我的 django 控制台中,我看到了
[08/Nov/2013 09:39:10] "OPTIONS /nodes HTTP/1.1" 301 0
仅供参考,我的 Angular 版本是 v1.2.0-rc.3 然后我已添加到我的应用中
config(['$sceDelegateProvider', function($sceDelegateProvider)
$sceDelegateProvider.resourceUrlWhitelist(['self', 'http://127.0.0.1']);
])
但没有任何改变:(
一个想法?
编辑
我认为问题来自 $resource,也许我在实施中错了。 我试图用 $http 而不是像
这样的 $resource 来删除一个节点$http.delete('http://127.0.0.1:8000/nodes/4/');
一切正常。
【问题讨论】:
当您使用相同的设置调用 PUT 时,它是否有效? 不,同样的行为 :( 我发布了一个答案,不确定是否可以完成,所以您需要尝试使用这些设置.. 顺便说一句。为什么使用 CORS?客户端是在不同的域上还是其他? 感谢您的帮助,购买一切都没有改变:(。我使用 CORS 因为我的 django 在 localhost:8000 上服务,而我的 angular 应用程序在 localhost:8888 上。在未来它是一个可能会公开的 API我需要 CORS 如果客户端在 :8888 上,则尝试相应地更改CORS_ORIGIN_WHITELIST
。你这样做了吗?我记得我前段时间遇到了同样的问题,这些设置有帮助,所以也许可以尝试一下,删除一些部分,看看会发生什么。你还可以用请求发送的确切标题更新你的帖子吗?所以我们有更多细节。
【参考方案1】:
您可能需要相应地调整您的 django 设置:
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_WHITELIST = ('127.0.0.1:8000', )
SESSION_COOKIE_DOMAIN = '127.0.0.1'
CSRF_COOKIE_DOMAIN = '127.0.0.1'
另外,如果您使用 csrf 令牌,请不要忘记:
app.run(function($http)
$http.defaults.headers.post['X-CSRFToken'] = $.cookie('csrftoken');
);
【讨论】:
【参考方案2】:事实上,问题来自于 Django,它增加了一个试用空间。
然后当 Angular 尝试获取 http://test/url
但 django 将其重定向到 http://test/url/
此重定向意味着数据丢失。
我的解决方案是将this modification 放入resource.js 文件中。
其他解决方案也是可能的,Django 端的 APPEND_SLASH 为 False
【讨论】:
以上是关于使用 angular 向 django-rest 发送 DELETE 请求被解释为 OPTIONS的主要内容,如果未能解决你的问题,请参考以下文章
使用 django-rest 框架中的 GET 方法将 url 作为参数传递?
使用 django-allauth 和 django-rest 框架
如何使用模型序列化器在 django-rest 中序列化一对多关系?