aboutsummaryrefslogtreecommitdiffstats
path: root/djangorestframework/parsers.py
diff options
context:
space:
mode:
authorspiq2011-03-04 12:28:20 +0200
committerspiq2011-03-04 12:28:20 +0200
commit91b33659b562f26665cebc3c7d8aba6d57e9386c (patch)
tree254239bbc2b0c1ffab085e7ac4ae3184aedbe041 /djangorestframework/parsers.py
parent30fd23d7f5a2d468e39fa8b66bae508df88a4d0d (diff)
downloaddjango-rest-framework-91b33659b562f26665cebc3c7d8aba6d57e9386c.tar.bz2
fix for PUT files
Diffstat (limited to 'djangorestframework/parsers.py')
-rw-r--r--djangorestframework/parsers.py81
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
+