aboutsummaryrefslogtreecommitdiffstats
path: root/djangorestframework/parsers.py
diff options
context:
space:
mode:
authorTom Christie2011-05-10 10:49:28 +0100
committerTom Christie2011-05-10 10:49:28 +0100
commit8f58ee489d34b200acfc2666816eb32e47c8cef5 (patch)
treee1c4a273b46abd9ad7c74d6837108d31a7b76d9c /djangorestframework/parsers.py
parentd373b3a067796b8e181be9368fa24e89c572c45e (diff)
downloaddjango-rest-framework-8f58ee489d34b200acfc2666816eb32e47c8cef5.tar.bz2
Getting the API into shape
Diffstat (limited to 'djangorestframework/parsers.py')
-rw-r--r--djangorestframework/parsers.py75
1 files changed, 47 insertions, 28 deletions
diff --git a/djangorestframework/parsers.py b/djangorestframework/parsers.py
index 6d6bd5ce..da700367 100644
--- a/djangorestframework/parsers.py
+++ b/djangorestframework/parsers.py
@@ -1,5 +1,6 @@
-"""Django supports parsing the content of an HTTP request, but only for form POST requests.
-That behaviour is sufficient for dealing with standard HTML forms, but it doesn't map well
+"""
+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:
@@ -8,54 +9,72 @@ We need a method to be able to:
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.multipartparser import MultiPartParser as DjangoMPParser
-from django.utils import simplejson as json
-from djangorestframework.response import ErrorResponse
+from django.http.multipartparser import MultiPartParser as DjangoMultiPartParser
+from django.utils import simplejson as json
from djangorestframework import status
-from djangorestframework.utils import as_tuple
-from djangorestframework.utils.mediatypes import MediaType
from djangorestframework.compat import parse_qs
+from djangorestframework.response import ErrorResponse
+from djangorestframework.utils import as_tuple
+from djangorestframework.utils.mediatypes import media_type_matches
+
+__all__ = (
+ 'BaseParser',
+ 'JSONParser',
+ 'PlainTextParser',
+ 'FormParser',
+ 'MultiPartParser'
+)
class BaseParser(object):
- """All parsers should extend BaseParser, specifying a media_type attribute,
- and overriding the parse() method."""
+ """
+ All parsers should extend BaseParser, specifying a media_type attribute,
+ and overriding the parse() method.
+ """
media_type = None
def __init__(self, view):
"""
- Initialise the parser with the View instance as state,
- in case the parser needs to access any metadata on the View object.
-
+ Initialize the parser with the ``View`` instance as state,
+ in case the parser needs to access any metadata on the ``View`` object.
"""
self.view = view
- @classmethod
- def handles(self, media_type):
+ def can_handle_request(self, media_type):
"""
- Returns `True` if this parser is able to deal with the given MediaType.
+ Returns `True` if this parser is able to deal with the given media type.
+
+ The default implementation for this function is to check the ``media_type``
+ argument against the ``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 ``media_type`` attribute on the class.
"""
- return media_type.match(self.media_type)
+ return media_type_matches(media_type, self.media_type)
def parse(self, stream):
- """Given a stream to read from, return the deserialized output.
- The return value may be of any type, but for many parsers it might typically be a dict-like object."""
+ """
+ Given a stream to read from, return the deserialized output.
+ The return value may be of any type, but for many parsers it might typically be a dict-like object.
+ """
raise NotImplementedError("BaseParser.parse() Must be overridden to be implemented.")
class JSONParser(BaseParser):
- media_type = MediaType('application/json')
+ media_type = 'application/json'
def parse(self, stream):
try:
return json.load(stream)
except ValueError, exc:
- raise ErrorResponse(status.HTTP_400_BAD_REQUEST, {'detail': 'JSON parse error - %s' % str(exc)})
+ raise ErrorResponse(status.HTTP_400_BAD_REQUEST,
+ {'detail': 'JSON parse error - %s' % unicode(exc)})
class DataFlatener(object):
- """Utility object for flatening dictionaries of lists. Useful for "urlencoded" decoded data."""
+ """Utility object for flattening dictionaries of lists. Useful for "urlencoded" decoded data."""
def flatten_data(self, data):
"""Given a data dictionary {<key>: <value_list>}, returns a flattened dictionary
@@ -83,9 +102,9 @@ class PlainTextParser(BaseParser):
"""
Plain text parser.
- Simply returns the content of the stream
+ Simply returns the content of the stream.
"""
- media_type = MediaType('text/plain')
+ media_type = 'text/plain'
def parse(self, stream):
return stream.read()
@@ -98,7 +117,7 @@ class FormParser(BaseParser, DataFlatener):
In order to handle select multiple (and having possibly more than a single value for each parameter),
you can customize the output by subclassing the method 'is_a_list'."""
- media_type = MediaType('application/x-www-form-urlencoded')
+ media_type = 'application/x-www-form-urlencoded'
"""The value of the parameter when the select multiple is empty.
Browsers are usually stripping the select multiple that have no option selected from the parameters sent.
@@ -138,14 +157,14 @@ class MultipartData(dict):
dict.__init__(self, data)
self.FILES = files
-class MultipartParser(BaseParser, DataFlatener):
- media_type = MediaType('multipart/form-data')
+class MultiPartParser(BaseParser, DataFlatener):
+ media_type = 'multipart/form-data'
RESERVED_FORM_PARAMS = ('csrfmiddlewaretoken',)
def parse(self, stream):
upload_handlers = self.view.request._get_upload_handlers()
- django_mpp = DjangoMPParser(self.view.request.META, stream, upload_handlers)
- data, files = django_mpp.parse()
+ django_parser = DjangoMultiPartParser(self.view.request.META, stream, upload_handlers)
+ data, files = django_parser.parse()
# Flatening data, files and combining them
data = self.flatten_data(dict(data.iterlists()))