mirror of
				https://github.com/encode/django-rest-framework.git
				synced 2025-11-04 09:57:55 +03:00 
			
		
		
		
	forms and multipat parsers now flaten data
This commit is contained in:
		
							parent
							
								
									91b33659b5
								
							
						
					
					
						commit
						033c0ae797
					
				| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 ``{<attr_name>: <value_list>}``, 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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user