我想跟随我的新django项目的RESTful模式,并且我想知道在发出PUT / DELETE请求时参数的位置。
据我所知,我只看到GET&请求中的POST QueryDict,没有其他人。 Django是否在请求中添加了新的PUT或DELETE QueryDict,还是将参数添加到GET或POST QueryDict?
感谢您的帮助。
答案 0 :(得分:85)
我正在使用django v1.5。我主要使用 QueryDict 来解决问题:
from django.http import QueryDict
put = QueryDict(request.body)
description = put.get('description')
和* .coffee
$.ajax
url: "/policy/#{policyId}/description/"
type: "PUT"
data:
description: value
success: (data) ->
alert data.body
fail: (data) ->
alert "fail"
您可以here查找更多信息。我希望这可以帮到你。祝你好运:)
答案 1 :(得分:39)
我假设你问的是你是否可以有这样的方法:
def restaction(request, id):
if request.method == "PUT":
someparam = request.PUT["somekey"]
答案是否定的,你不能。 Django没有为PUT,OPTIONS和DELETE请求构建这样的字典,其解释是here。
总结一下,REST的概念是,您交换的数据可能比简单的键值映射要复杂得多。例如,PUTting图像,或使用json。框架无法知道您可能想要发送数据的多种方式,因此它做了显而易见的事情 - 让您处理这一点。另请参阅this question的答案,其中给出了相同的答案。
现在,您在哪里找到数据?好吧,根据docs,django 1.2功能request.raw_post_data
。作为抬头,it looks like django 1.3 will support request.read()
即文件般的语义。
答案 2 :(得分:12)
Ninefiger的回答是正确的。但是,有一些解决方法。
如果您正在为Django项目编写REST样式API,我强烈建议您使用tastypie。您将节省大量时间并保证API的结构更加结构化。您还可以查看tastypie是如何做到的(访问PUT和DELETE数据)。
答案 3 :(得分:5)
您可以在django-piston's code中看到为PUT方法获取QueryDict的示例(请参阅coerce_put_post方法)
答案 4 :(得分:3)
有一个问题我无法解决如何从request
解析multipart / form-data。 QueryDict(request.body)
没有帮助我。
所以,我找到了一个解决方案。我开始使用它:
from django.http.multipartparser import MultiPartParser
您可以从request
获取数据,如:
MultiPartParser(request.META, request, request.upload_handlers).parse()
答案 5 :(得分:1)
只要参数在 URL 中,您仍然可以使用 self.request.GET
获取 PUT 和 DELETE 方法的参数。
例如
DELETE /api/comment/?comment_id=40 HTTP/1.1
在 APIView 中,您可以这样做:
class CommentAPIView(APIView):
# ... ...
def delete(self, request):
user = request.user.id
comment_id = self.request.GET['comment_id']
try:
cmt = get_object_or_404(Comment, id=comment_id, user=user)
cmt.delete()
return Response(status=204)
except Exception, e:
return Response({'error': str(e)})
答案 6 :(得分:0)
我的方法是重写调度函数,以便可以使用QueryDict()从主体数据中设置一个变量
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import QueryDict
from django.views.generic import View
class GenericView(View):
def dispatch(self, request, *args, **kwargs):
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
# if we have a request with potential body data utilize QueryDict()
if request.method.lower() in ['post', 'put', 'patch']:
self.request_body_data = {k: v[0] if len(v)==1 else v for k, v in QueryDict(request.body).lists()}
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs)
class ObjectDetailView(LoginRequiredMixin, GenericView):
def put(self, request, object_id):
print("updating object", object_id)
print(self.request_body_data)
def patch(self, request, object_id):
print("updating object", object_id)
print(self.request_body_data)
答案 7 :(得分:0)
Django无法轻松访问PUT
请求正文中的参数。我的解决方法:
def coerce_put_post(request):
"""
Django doesn't particularly understand REST.
In case we send data over PUT, Django won't
actually look at the data and load it. We need
to twist its arm here.
The try/except abominiation here is due to a bug
in mod_python. This should fix it.
"""
if request.method == "PUT":
# Bug fix: if _load_post_and_files has already been called, for
# example by middleware accessing request.POST, the below code to
# pretend the request is a POST instead of a PUT will be too late
# to make a difference. Also calling _load_post_and_files will result
# in the following exception:
# AttributeError: You cannot set the upload handlers after the upload has been processed.
# The fix is to check for the presence of the _post field which is set
# the first time _load_post_and_files is called (both by wsgi.py and
# modpython.py). If it's set, the request has to be 'reset' to redo
# the query value parsing in POST mode.
if hasattr(request, '_post'):
del request._post
del request._files
try:
request.method = "POST"
request._load_post_and_files()
#body = request.body
request.method = "PUT"
except AttributeError:
request.META['REQUEST_METHOD'] = 'POST'
request._load_post_and_files()
request.META['REQUEST_METHOD'] = 'PUT'
request.PUT = request.POST
@api_view(["PUT", "POST"])
def submit(request):
coerce_put_post(request)
description=request.PUT.get('k', 0)
return HttpResponse(f"Received {description}")