Source

Django REST Framework / djangorestframework / parsers.py

Tom Christie 9b1c468 


tom ...@tomchris… 32b9912 
spiq a341feb 
tom ...@tomchris… 32b9912 

markotibold 923662d 


tom ...@tomchris… 32b9912 

Tom Christie 9b1c468 
Alen Mujezinovic 8b722ab 
Tom Christie 9b1c468 
astraw deffb84 
tom ...@tomchris… 96614c8 
Tom Christie 9b1c468 
Tom Christie eed0f39 
Tom Christie 9b1c468 

tom ...@tomchris… 96614c8 
markotibold f01267f 
Tom Christie 9b1c468 




markotibold 923662d 
markotibold f01267f 
Tom Christie 9b1c468 
tom ...@tomchris… 66cd919 


Tom Christie 9b1c468 
markotibold 923662d 

Tom Christie 9b1c468 
Tom Christie 5b42173 
tom ...@tomchris… 66cd919 

tom ...@tomchris… 32b9912 

Tom Christie 9b1c468 
markotibold 923662d 
tom ...@tomchris… 32b9912 

tom ...@tomchris… 66cd919 
Tom Christie 44824e5 
tom ...@tomchris… 32b9912 
markotibold 923662d 
Tom Christie 9b1c468 
markotibold 923662d 

Tom Christie 9b1c468 


markotibold 923662d 
tom ...@tomchris… 32b9912 
Tom Christie 9cdf703 
tom ...@tomchris… 32b9912 

Tom Christie 9b1c468 
markotibold 923662d 
Tom Christie 44824e5 
Tom Christie 9b1c468 
tom ...@tomchris… 32b9912 
tom ...@tomchris… 66cd919 


markotibold 923662d 


Tom Christie 5b42173 
Tom Christie 9b1c468 
tom ...@tomchris… 66cd919 
tom ...@tomchris… 32b9912 
Tom Christie 1b0ec89 





tom ...@tomchris… 66cd919 
Tom Christie 44824e5 
tom ...@tomchris… 66cd919 
Tom Christie 9b1c468 

tom ...@tomchris… 66cd919 

Tom Christie eed0f39 

markotibold f01267f 
Tom Christie eed0f39 
markotibold f01267f 
Tom Christie eed0f39 














Jens Alm b59491c 

tom ...@tomchris… 32b9912 
Tom Christie ea7e98f 

Tom Christie 0f0a16e 
Tom Christie ea7e98f 
Tom Christie 5b42173 
Tom Christie 9b1c468 
Tom Christie ea7e98f 

Tom Christie 1b0ec89 





Tom Christie 44824e5 
Tom Christie ea7e98f 

Tom Christie 1b0ec89 
Tom Christie 0f0a16e 
Tom Christie 1b0ec89 

sebpiq 3f4f275 
Tom Christie 9b1c468 
tom ...@tomchris… 66cd919 
Tom Christie 1b0ec89 



Tom Christie 5b42173 

Tom Christie 1b0ec89 
Alen Mujezinovic 8b722ab 
Tom Christie 1b0ec89 



Tom Christie 0f0a16e 
Tom Christie 1b0ec89 



spiq bbc87c2 
tom ...@tomchris… 32b9912 
Tom Christie 1b0ec89 


Tom Christie 5b42173 

Tom Christie 1b0ec89 
tom ...@tomchris… 32b9912 
astraw deffb84 




Tom Christie 1b0ec89 
spiq a341feb 
Jens Alm 9def52a 




Tom Christie cc57967 
"""
Django supports parsing the content of an HTTP request, but only for form POST requests.
That behavior is sufficient for dealing with standard HTML forms, but it doesn't map well
to general HTTP requests.

We need a method to be able to:

1.) Determine the parsed content on a request for methods other than POST (eg typically also PUT)

2.) Determine the parsed content on a request for media types other than application/x-www-form-urlencoded
   and multipart/form-data.  (eg also handle multipart/json)
"""

from django.http import QueryDict
from django.http.multipartparser import MultiPartParser as DjangoMultiPartParser
from django.http.multipartparser import MultiPartParserError
from django.utils import simplejson as json
from djangorestframework import status
from djangorestframework.compat import yaml
from djangorestframework.response import ErrorResponse
from djangorestframework.utils.mediatypes import media_type_matches


__all__ = (
    'BaseParser',
    'JSONParser',
    'PlainTextParser',
    'FormParser',
    'MultiPartParser',
    'YAMLParser',
)


class BaseParser(object):
    """
    All parsers should extend :class:`BaseParser`, specifying a :attr:`media_type` attribute,
    and overriding the :meth:`parse` method.
    """

    media_type = None

    def __init__(self, view):
        """
        Initialize the parser with the ``View`` instance as state,
        in case the parser needs to access any metadata on the :obj:`View` object.
        """
        self.view = view
    
    def can_handle_request(self, content_type):
        """
        Returns :const:`True` if this parser is able to deal with the given *content_type*.
        
        The default implementation for this function is to check the *content_type*
        argument against the :attr:`media_type` attribute set on the class to see if
        they match.
        
        This may be overridden to provide for other behavior, but typically you'll
        instead want to just set the :attr:`media_type` attribute on the class.
        """
        return media_type_matches(self.media_type, content_type)

    def parse(self, stream):
        """
        Given a *stream* to read from, return the deserialized output.
        Should return a 2-tuple of (data, files).
        """
        raise NotImplementedError("BaseParser.parse() Must be overridden to be implemented.")


class JSONParser(BaseParser):
    """
    Parses JSON-serialized data.
    """

    media_type = 'application/json'

    def parse(self, stream):
        """
        Returns a 2-tuple of `(data, files)`.

        `data` will be an object which is the parsed content of the response.
        `files` will always be `None`.
        """
        try:
            return (json.load(stream), None)
        except ValueError, exc:
            raise ErrorResponse(status.HTTP_400_BAD_REQUEST,
                                {'detail': 'JSON parse error - %s' % unicode(exc)})


if yaml:
    class YAMLParser(BaseParser):
        """
        Parses YAML-serialized data.
        """
    
        media_type = 'application/yaml'
    
        def parse(self, stream):
            """
            Returns a 2-tuple of `(data, files)`.
    
            `data` will be an object which is the parsed content of the response.
            `files` will always be `None`.
            """
            try:
                return (yaml.safe_load(stream), None)
            except ValueError, exc:
                raise ErrorResponse(status.HTTP_400_BAD_REQUEST,
                                    {'detail': 'YAML parse error - %s' % unicode(exc)})
else:
    YAMLParser = None

class PlainTextParser(BaseParser):
    """
    Plain text parser.
    """

    media_type = 'text/plain'

    def parse(self, stream):
        """
        Returns a 2-tuple of `(data, files)`.
        
        `data` will simply be a string representing the body of the request.
        `files` will always be `None`.
        """
        return (stream.read(), None)


class FormParser(BaseParser):
    """
    Parser for form data.
    """

    media_type = 'application/x-www-form-urlencoded'

    def parse(self, stream):
        """
        Returns a 2-tuple of `(data, files)`.
        
        `data` will be a :class:`QueryDict` containing all the form parameters.
        `files` will always be :const:`None`.
        """
        data = QueryDict(stream.read())
        return (data, None)


class MultiPartParser(BaseParser):
    """
    Parser for multipart form data, which may include file data.
    """

    media_type = 'multipart/form-data'

    def parse(self, stream):
        """
        Returns a 2-tuple of `(data, files)`.
        
        `data` will be a :class:`QueryDict` containing all the form parameters.
        `files` will be a :class:`QueryDict` containing all the form files.
        """
        upload_handlers = self.view.request._get_upload_handlers()
        try:
            django_parser = DjangoMultiPartParser(self.view.request.META, stream, upload_handlers)
        except MultiPartParserError, exc:
            raise ErrorResponse(status.HTTP_400_BAD_REQUEST,
                                {'detail': 'multipart parse error - %s' % unicode(exc)})
        return django_parser.parse()

DEFAULT_PARSERS = ( JSONParser,
                    FormParser,
                    MultiPartParser )

if YAMLParser:
    DEFAULT_PARSERS += ( YAMLParser, )
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.