diff options
| author | spiq | 2011-03-04 12:28:20 +0200 |
|---|---|---|
| committer | spiq | 2011-03-04 12:28:20 +0200 |
| commit | 91b33659b562f26665cebc3c7d8aba6d57e9386c (patch) | |
| tree | 254239bbc2b0c1ffab085e7ac4ae3184aedbe041 /djangorestframework/parsers.py | |
| parent | 30fd23d7f5a2d468e39fa8b66bae508df88a4d0d (diff) | |
| download | django-rest-framework-91b33659b562f26665cebc3c7d8aba6d57e9386c.tar.bz2 | |
fix for PUT files
Diffstat (limited to 'djangorestframework/parsers.py')
| -rw-r--r-- | djangorestframework/parsers.py | 81 |
1 files changed, 48 insertions, 33 deletions
diff --git a/djangorestframework/parsers.py b/djangorestframework/parsers.py index 7c686ca8..e5dd7df4 100644 --- a/djangorestframework/parsers.py +++ b/djangorestframework/parsers.py @@ -1,3 +1,7 @@ +from StringIO import StringIO + +from django.http.multipartparser import MultiPartParser as DjangoMPParser + from djangorestframework.response import ResponseException from djangorestframework import status @@ -6,6 +10,10 @@ try: except ImportError: import simplejson as json +try: + from urlparse import parse_qs +except ImportError: + from cgi import parse_qs class ParserMixin(object): parsers = () @@ -75,50 +83,57 @@ class FormParser(BaseParser): """The default parser for form data. Return a dict containing a single value for each non-reserved parameter. """ - + # TODO: not good, because posted/put lists are flattened !!! media_type = 'application/x-www-form-urlencoded' def parse(self, input): - # The FormParser doesn't parse the input as other parsers would, since Django's already done the - # form parsing for us. We build the content object from the request directly. request = self.resource.request if request.method == 'PUT': - # Fix from piston to force Django to give PUT requests the same - # form processing that POST requests get... - # - # 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() - request.method = "PUT" - except AttributeError: - request.META['REQUEST_METHOD'] = 'POST' - request._load_post_and_files() - request.META['REQUEST_METHOD'] = 'PUT' + data = parse_qs(input) + # Flattening the parsed query data + for key, val in data.items(): + data[key] = val[0] + + if request.method == 'POST': + # Django has already done the form parsing for us. + data = dict(request.POST.items()) # Strip any parameters that we are treating as reserved - data = {} - for (key, val) in request.POST.items(): - if key not in self.resource.RESERVED_FORM_PARAMS: - data[key] = val - + for key in data: + if key in self.resource.RESERVED_FORM_PARAMS: + data.pop(key) return data # TODO: Allow parsers to specify multiple media_types class MultipartParser(FormParser): media_type = 'multipart/form-data' + def parse(self, input): + request = self.resource.request + + if request.method == 'PUT': + upload_handlers = request._get_upload_handlers() + django_mpp = DjangoMPParser(request.META, StringIO(input), upload_handlers) + data, files = django_mpp.parse() + data = dict(data) + files = dict(files) + + if request.method == 'POST': + # Django has already done the form parsing for us. + data = dict(request.POST) + files = dict(request.FILES) + + # Flattening, then merging the POSTED/PUT data/files + for key, val in dict(data).items(): + data[key] = val[0] + for key, val in dict(files).items(): + files[key] = val[0].read() + data.update(files) + + # Strip any parameters that we are treating as reserved + for key in data: + if key in self.resource.RESERVED_FORM_PARAMS: + data.pop(key) + return data + |
