From 033c0ae797e0bbb39a0687592d5b5f8eceb4d4dd Mon Sep 17 00:00:00 2001 From: spiq Date: Fri, 4 Mar 2011 17:06:44 +0200 Subject: [PATCH] forms and multipat parsers now flaten data --- djangorestframework/content.py | 8 +---- djangorestframework/parsers.py | 53 ++++++++++++++++++++++------------ 2 files changed, 36 insertions(+), 25 deletions(-) diff --git a/djangorestframework/content.py b/djangorestframework/content.py index abe2069ed..dd40f8f1a 100644 --- a/djangorestframework/content.py +++ b/djangorestframework/content.py @@ -60,7 +60,6 @@ class OverloadedContentMixin(ContentMixin): Note that content_type may be None if it is unset.""" if not request.META.get('CONTENT_LENGTH', None) and not request.META.get('TRANSFER_ENCODING', None): return None - content_type = request.META.get('CONTENT_TYPE', None) if (request.method == 'POST' and self.CONTENT_PARAM and @@ -74,11 +73,6 @@ class OverloadedContentMixin(ContentMixin): return (content_type, request.POST[self.CONTENT_PARAM]) elif request.method == 'PUT': f = SocketFile(request.environ['wsgi.input'], request.META['CONTENT_LENGTH']) - returned = (content_type, f.read()) - return returned - #try: - # f.close() - #except Exception as e: - # print 'exception', e + return (content_type, f.read()) else: return (content_type, request.raw_post_data) diff --git a/djangorestframework/parsers.py b/djangorestframework/parsers.py index e5dd7df47..c334f7292 100644 --- a/djangorestframework/parsers.py +++ b/djangorestframework/parsers.py @@ -78,12 +78,36 @@ class JSONParser(BaseParser): class XMLParser(BaseParser): media_type = 'application/xml' +class DataFlatener(object): -class FormParser(BaseParser): + def flatten_data(self, data): + """Given a data dictionary ``{: }``, returns a flattened dictionary according to :meth:`FormParser.is_a_list`. + """ + #TODO : document + test + flatdata = dict() + for attr_name, attr_value in data.items(): + if self.is_a_list(attr_name): + if isinstance(attr_value, list): + flatdata[attr_name] = attr_value + else: + flatdata[attr_name] = [attr_value] + else: + if isinstance(attr_value, list): + flatdata[attr_name] = attr_value[0] + else: + flatdata[attr_name] = attr_value + return flatdata + + def is_a_list(self, attr_name): + """ """ + #TODO: document + return False + +class FormParser(BaseParser, DataFlatener): """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 !!! + # TODO: writing tests for PUT files + normal data media_type = 'application/x-www-form-urlencoded' def parse(self, input): @@ -91,13 +115,12 @@ class FormParser(BaseParser): if 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()) + data = request.POST + + data = self.flatten_data(data) # Strip any parameters that we are treating as reserved for key in data: @@ -106,7 +129,7 @@ class FormParser(BaseParser): return data # TODO: Allow parsers to specify multiple media_types -class MultipartParser(FormParser): +class MultipartParser(BaseParser, DataFlatener): media_type = 'multipart/form-data' def parse(self, input): @@ -116,19 +139,14 @@ class MultipartParser(FormParser): 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': + elif request.method == 'POST': # Django has already done the form parsing for us. - data = dict(request.POST) - files = dict(request.FILES) + data = request.POST + files = 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 = self.flatten_data(data) + files = self.flatten_data(files) data.update(files) # Strip any parameters that we are treating as reserved @@ -136,4 +154,3 @@ class MultipartParser(FormParser): if key in self.resource.RESERVED_FORM_PARAMS: data.pop(key) return data -