Added media_type to .parse() - Consistency with renderer API.

This commit is contained in:
Tom Christie 2012-10-17 22:39:07 +01:00
parent 4231995fbd
commit fb56f215ae
5 changed files with 35 additions and 30 deletions

View File

@ -101,6 +101,12 @@ The arguments passed to `.parse()` are:
A stream-like object representing the body of the request.
### media_type
Optional. If provided, this is the media type of the incoming request.
Depending on the request's `Content-Type:` header, this may be more specific than the renderer's `media_type` attribute, and may include media type parameters. For example `"text/plain; charset=utf-8"`.
### parser_context
Optional. If supplied, this argument will be a dictionary containing any additional context that may be required to parse the request content.
@ -118,7 +124,7 @@ The following is an example plaintext parser that will populate the `request.DAT
media_type = 'text/plain'
def parse(self, stream, parser_context=None):
def parse(self, stream, media_type=None, parser_context=None):
"""
Simply return a string representing the body of the request.
"""
@ -135,7 +141,7 @@ For example:
A naive raw file upload parser.
"""
def parse(self, stream, parser_context):
def parse(self, stream, media_type=None, parser_context=None):
content = stream.read()
name = 'example.dat'
content_type = 'application/octet-stream'

View File

@ -1,14 +1,8 @@
"""
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.
Parsers are used to parse the content of incoming 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)
They give us a generic way of being able to handle various media types
on the request, such as form content or json encoded data.
"""
from django.http import QueryDict
@ -37,10 +31,10 @@ class BaseParser(object):
media_type = None
def parse(self, stream, parser_context=None):
def parse(self, stream, media_type=None, parser_context=None):
"""
Given a stream to read from, return the deserialized output.
Should return parsed data, or a DataAndFiles object consisting of the
Given a stream to read from, return the parsed representation.
Should return parsed data, or a `DataAndFiles` object consisting of the
parsed data and files.
"""
raise NotImplementedError(".parse() must be overridden.")
@ -53,7 +47,7 @@ class JSONParser(BaseParser):
media_type = 'application/json'
def parse(self, stream, parser_context=None):
def parse(self, stream, media_type=None, parser_context=None):
"""
Returns a 2-tuple of `(data, files)`.
@ -73,7 +67,7 @@ class YAMLParser(BaseParser):
media_type = 'application/yaml'
def parse(self, stream, parser_context=None):
def parse(self, stream, media_type=None, parser_context=None):
"""
Returns a 2-tuple of `(data, files)`.
@ -93,7 +87,7 @@ class FormParser(BaseParser):
media_type = 'application/x-www-form-urlencoded'
def parse(self, stream, parser_context=None):
def parse(self, stream, media_type=None, parser_context=None):
"""
Returns a 2-tuple of `(data, files)`.
@ -111,7 +105,7 @@ class MultiPartParser(BaseParser):
media_type = 'multipart/form-data'
def parse(self, stream, parser_context=None):
def parse(self, stream, media_type=None, parser_context=None):
"""
Returns a DataAndFiles object.
@ -138,7 +132,7 @@ class XMLParser(BaseParser):
media_type = 'application/xml'
def parse(self, stream, parser_context=None):
def parse(self, stream, media_type=None, parser_context=None):
try:
tree = ET.parse(stream)
except (ExpatError, ETParseError, ValueError), exc:

View File

@ -1,9 +1,10 @@
"""
Renderers are used to serialize a View's output into specific media types.
Renderers are used to serialize a response into specific media types.
Django REST framework also provides HTML and PlainText renderers that help self-document the API,
by serializing the output along with documentation regarding the View, output status and headers,
and providing forms and links depending on the allowed methods, renderers and parsers on the View.
They give us a generic way of being able to handle various media types
on the response, such as JSON encoded data or HTML output.
REST framework also provides an HTML renderer the renders the browseable API.
"""
import string
from django import forms
@ -23,8 +24,8 @@ from rest_framework import serializers, parsers
class BaseRenderer(object):
"""
All renderers must extend this class, set the :attr:`media_type` attribute,
and override the :meth:`render` method.
All renderers should extend this class, setting the `media_type`
and `format` attributes, and override the `.render()` method.
"""
media_type = None

View File

@ -260,15 +260,19 @@ class Request(object):
May raise an `UnsupportedMediaType`, or `ParseError` exception.
"""
if self.stream is None or self.content_type is None:
stream = self.stream
media_type = self.content_type
if stream is None or media_type is None:
return (None, None)
parser = self.negotiator.select_parser(self.parsers, self.content_type)
parser = self.negotiator.select_parser(self.parsers, media_type)
if not parser:
raise exceptions.UnsupportedMediaType(self.content_type)
raise exceptions.UnsupportedMediaType(media_type)
parsed = parser.parse(stream, media_type, self.parser_context)
parsed = parser.parse(self.stream, self.parser_context)
# Parser classes may return the raw data, or a
# DataAndFiles object. Unpack the result as required.
try:

View File

@ -27,7 +27,7 @@ factory = RequestFactory()
class PlainTextParser(BaseParser):
media_type = 'text/plain'
def parse(self, stream, parser_context=None):
def parse(self, stream, media_type=None, parser_context=None):
"""
Returns a 2-tuple of `(data, files)`.