在django-rest-framework

时间:2015-12-17 17:02:52

标签: python django django-rest-framework

使用django-rest-framework时,我在解析多部分表单数据时遇到了一些困难。我已经设置了一个最小视图来回显请求数据:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.parsers import MultiPartParser, FormParser


class FileUpload(APIView):
    parser_classes = (MultiPartParser, FormParser, )

    def post(self, request, format=None, *args, **kwargs):
        return Response({'raw': request.data, 'data': request._request.POST,
                         'files': str(request._request.FILES)})

我希望raw(我承认稍微命名)包含与request._request.POSTrequest._request.FILES相同的数据。

如果POST Content-Type= application/x-www-form-urlencoded$ http -v --form POST http://localhost:8000/upload/api/ course=3 name=name POST /upload/api/ HTTP/1.1 Accept: */* Accept-Encoding: gzip, deflate Connection: keep-alive Content-Length: 18 Content-Type: application/x-www-form-urlencoded; charset=utf-8 Host: localhost:8000 User-Agent: HTTPie/0.9.2 course=3&name=name HTTP/1.0 200 OK Allow: POST, OPTIONS Content-Type: application/json Date: Thu, 17 Dec 2015 16:52:37 GMT Server: WSGIServer/0.2 CPython/3.4.3 Vary: Accept, Cookie X-Frame-Options: SAMEORIGIN { "data": { "course": "3", "name": "name" }, "files": "<MultiValueDict: {}>", "raw": { "course": "3", "name": "name" } } 视图,则按预期工作:

Content-Type=multipart/form-data

但是,如果我使用$ http -v --form POST http://localhost:8000/upload/api/ file@~/Projects/lms/manage.py course=3 name=name POST /upload/api/ HTTP/1.1 Accept: */* Accept-Encoding: gzip, deflate Connection: keep-alive Content-Length: 577 Content-Type: multipart/form-data; boundary=634ec7c7e89a487b89c1c07c0d24744c Host: localhost:8000 User-Agent: HTTPie/0.9.2 --634ec7c7e89a487b89c1c07c0d24744c Content-Disposition: form-data; name="course" 3 --634ec7c7e89a487b89c1c07c0d24744c Content-Disposition: form-data; name="name" name --634ec7c7e89a487b89c1c07c0d24744c Content-Disposition: form-data; name="file"; filename="manage.py" #!/usr/bin/env python import os import sys if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local") from django.core.management import execute_from_command_line execute_from_command_line(sys.argv) --634ec7c7e89a487b89c1c07c0d24744c-- HTTP/1.0 200 OK Allow: POST, OPTIONS Content-Type: application/json Date: Thu, 17 Dec 2015 16:55:44 GMT Server: WSGIServer/0.2 CPython/3.4.3 Vary: Accept, Cookie X-Frame-Options: SAMEORIGIN { "data": { "course": "3", "name": "name" }, "files": "<MultiValueDict: {'file': [<InMemoryUploadedFile: manage.py ()>]}>", "raw": {} } 发帖,我会收到以下内容:

PUT

我在这里遗漏了什么吗?我在这里使用HTTPIE生成请求,但curl存在相同的行为,所以我很确定这不是问题。我使用的是djangorestframework == 3.3.0和Django == 1.8.4

编辑:

似乎$ http -v --form PUT http://localhost:8000/upload/api/ file@~/Projects/lms/manage.py course=3 name=name PUT /upload/api/ HTTP/1.1 Accept: */* Accept-Encoding: gzip, deflate Connection: keep-alive Content-Length: 577 Content-Type: multipart/form-data; boundary=98feb59a8abe4bfb95a7321f536ed800 Host: localhost:8000 User-Agent: HTTPie/0.9.2 --98feb59a8abe4bfb95a7321f536ed800 Content-Disposition: form-data; name="course" 3 --98feb59a8abe4bfb95a7321f536ed800 Content-Disposition: form-data; name="name" name --98feb59a8abe4bfb95a7321f536ed800 Content-Disposition: form-data; name="file"; filename="manage.py" #!/usr/bin/env python import os import sys if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local") from django.core.management import execute_from_command_line execute_from_command_line(sys.argv) --98feb59a8abe4bfb95a7321f536ed800-- HTTP/1.0 200 OK Allow: POST, PUT, OPTIONS Content-Type: application/json Date: Thu, 17 Dec 2015 18:10:34 GMT Server: WSGIServer/0.2 CPython/3.4.3 Vary: Accept, Cookie X-Frame-Options: SAMEORIGIN { "data": {}, "files": "<MultiValueDict: {}>", "raw": "<QueryDict: {'name': ['name'], 'course': ['3'], 'file': [<InMemoryUploadedFile: manage.py ()>]}>" } 到url(具有相同的请求)可以达到预期的结果:

PUT

所以我可以使用POST。然而,这并不理想,因为客户端无法控制文件的名称或服务器上的位置。从这个意义上说,PUT更合适。无论如何,当POST没有customSelect = ng.core .Component({ selector: 'custom-select', templateUrl: 'select.html', properties:[ 'valueProperty:valueProperty', 'value:value', 'options:options' ] }) .Class({ constructor:[ng.core.NgZone, function(zone) { this.zone = zone; }], ngOnInit:function() { this.unbindChanges = this.valueProperty.bindChanges(function() { this.zone.run(function() { this.value = this.valueProperty.currentValue(); }.bind(this)); }.bind(this)); }, ngOnDestroy:function() { this.unbindChanges(); } }); 时,我不明白为什么A有效。

1 个答案:

答案 0 :(得分:1)

它是您使用的版本的known issue。将django rest框架升级到最新版本将解决此问题。但是,您可以将请求作为解决方法。