Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
D
django-rest-framework
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
django-rest-framework
Commits
7abef9ac
Commit
7abef9ac
authored
Sep 03, 2012
by
Tom Christie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Parsers may return raw data, or a DataAndFiles object
parent
d180e984
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
40 additions
and
30 deletions
+40
-30
djangorestframework/parsers.py
+16
-15
djangorestframework/request.py
+11
-5
djangorestframework/tests/parsers.py
+3
-3
djangorestframework/tests/renderers.py
+2
-2
djangorestframework/tests/request.py
+0
-2
djangorestframework/utils/encoders.py
+7
-2
docs/tutorial/1-serialization.md
+1
-1
No files found.
djangorestframework/parsers.py
View file @
7abef9ac
...
@@ -36,6 +36,12 @@ __all__ = (
...
@@ -36,6 +36,12 @@ __all__ = (
)
)
class
DataAndFiles
(
object
):
def
__init__
(
self
,
data
,
files
):
self
.
data
=
data
self
.
files
=
files
class
BaseParser
(
object
):
class
BaseParser
(
object
):
"""
"""
All parsers should extend :class:`BaseParser`, specifying a :attr:`media_type` attribute,
All parsers should extend :class:`BaseParser`, specifying a :attr:`media_type` attribute,
...
@@ -80,7 +86,7 @@ class JSONParser(BaseParser):
...
@@ -80,7 +86,7 @@ class JSONParser(BaseParser):
`files` will always be `None`.
`files` will always be `None`.
"""
"""
try
:
try
:
return
(
json
.
load
(
stream
),
None
)
return
json
.
load
(
stream
)
except
ValueError
,
exc
:
except
ValueError
,
exc
:
raise
ParseError
(
'JSON parse error -
%
s'
%
unicode
(
exc
))
raise
ParseError
(
'JSON parse error -
%
s'
%
unicode
(
exc
))
...
@@ -100,7 +106,7 @@ class YAMLParser(BaseParser):
...
@@ -100,7 +106,7 @@ class YAMLParser(BaseParser):
`files` will always be `None`.
`files` will always be `None`.
"""
"""
try
:
try
:
return
(
yaml
.
safe_load
(
stream
),
None
)
return
yaml
.
safe_load
(
stream
)
except
(
ValueError
,
yaml
.
parser
.
ParserError
),
exc
:
except
(
ValueError
,
yaml
.
parser
.
ParserError
),
exc
:
raise
ParseError
(
'YAML parse error -
%
s'
%
unicode
(
exc
))
raise
ParseError
(
'YAML parse error -
%
s'
%
unicode
(
exc
))
...
@@ -119,7 +125,7 @@ class PlainTextParser(BaseParser):
...
@@ -119,7 +125,7 @@ class PlainTextParser(BaseParser):
`data` will simply be a string representing the body of the request.
`data` will simply be a string representing the body of the request.
`files` will always be `None`.
`files` will always be `None`.
"""
"""
return
(
stream
.
read
(),
None
)
return
stream
.
read
(
)
class
FormParser
(
BaseParser
):
class
FormParser
(
BaseParser
):
...
@@ -137,7 +143,7 @@ class FormParser(BaseParser):
...
@@ -137,7 +143,7 @@ class FormParser(BaseParser):
`files` will always be :const:`None`.
`files` will always be :const:`None`.
"""
"""
data
=
QueryDict
(
stream
.
read
())
data
=
QueryDict
(
stream
.
read
())
return
(
data
,
None
)
return
data
class
MultiPartParser
(
BaseParser
):
class
MultiPartParser
(
BaseParser
):
...
@@ -149,16 +155,17 @@ class MultiPartParser(BaseParser):
...
@@ -149,16 +155,17 @@ class MultiPartParser(BaseParser):
def
parse
(
self
,
stream
,
**
opts
):
def
parse
(
self
,
stream
,
**
opts
):
"""
"""
Returns a
2-tuple of `(data, files)`
.
Returns a
DataAndFiles object
.
`
data` will be a :class:
`QueryDict` containing all the form parameters.
`
.data` will be a
`QueryDict` containing all the form parameters.
`
files` will be a :class:
`QueryDict` containing all the form files.
`
.files` will be a
`QueryDict` containing all the form files.
"""
"""
meta
=
opts
[
'meta'
]
meta
=
opts
[
'meta'
]
upload_handlers
=
opts
[
'upload_handlers'
]
upload_handlers
=
opts
[
'upload_handlers'
]
try
:
try
:
parser
=
DjangoMultiPartParser
(
meta
,
stream
,
upload_handlers
)
parser
=
DjangoMultiPartParser
(
meta
,
stream
,
upload_handlers
)
return
parser
.
parse
()
data
,
files
=
parser
.
parse
()
return
DataAndFiles
(
data
,
files
)
except
MultiPartParserError
,
exc
:
except
MultiPartParserError
,
exc
:
raise
ParseError
(
'Multipart form parse error -
%
s'
%
unicode
(
exc
))
raise
ParseError
(
'Multipart form parse error -
%
s'
%
unicode
(
exc
))
...
@@ -171,19 +178,13 @@ class XMLParser(BaseParser):
...
@@ -171,19 +178,13 @@ class XMLParser(BaseParser):
media_type
=
'application/xml'
media_type
=
'application/xml'
def
parse
(
self
,
stream
,
**
opts
):
def
parse
(
self
,
stream
,
**
opts
):
"""
Returns a 2-tuple of `(data, files)`.
`data` will simply be a string representing the body of the request.
`files` will always be `None`.
"""
try
:
try
:
tree
=
ET
.
parse
(
stream
)
tree
=
ET
.
parse
(
stream
)
except
(
ExpatError
,
ETParseError
,
ValueError
),
exc
:
except
(
ExpatError
,
ETParseError
,
ValueError
),
exc
:
raise
ParseError
(
'XML parse error -
%
s'
%
unicode
(
exc
))
raise
ParseError
(
'XML parse error -
%
s'
%
unicode
(
exc
))
data
=
self
.
_xml_convert
(
tree
.
getroot
())
data
=
self
.
_xml_convert
(
tree
.
getroot
())
return
(
data
,
None
)
return
data
def
_xml_convert
(
self
,
element
):
def
_xml_convert
(
self
,
element
):
"""
"""
...
...
djangorestframework/request.py
View file @
7abef9ac
...
@@ -146,7 +146,7 @@ class Request(object):
...
@@ -146,7 +146,7 @@ class Request(object):
self
.
_load_method_and_content_type
()
self
.
_load_method_and_content_type
()
if
not
_hasattr
(
self
,
'_data'
):
if
not
_hasattr
(
self
,
'_data'
):
(
self
.
_data
,
self
.
_files
)
=
self
.
_parse
()
self
.
_data
,
self
.
_files
=
self
.
_parse
()
def
_load_method_and_content_type
(
self
):
def
_load_method_and_content_type
(
self
):
"""
"""
...
@@ -201,11 +201,11 @@ class Request(object):
...
@@ -201,11 +201,11 @@ class Request(object):
self
.
_CONTENTTYPE_PARAM
in
self
.
_data
):
self
.
_CONTENTTYPE_PARAM
in
self
.
_data
):
self
.
_content_type
=
self
.
_data
.
pop
(
self
.
_CONTENTTYPE_PARAM
)[
0
]
self
.
_content_type
=
self
.
_data
.
pop
(
self
.
_CONTENTTYPE_PARAM
)[
0
]
self
.
_stream
=
StringIO
(
self
.
_data
.
pop
(
self
.
_CONTENT_PARAM
)[
0
])
self
.
_stream
=
StringIO
(
self
.
_data
.
pop
(
self
.
_CONTENT_PARAM
)[
0
])
(
self
.
_data
,
self
.
_files
)
=
self
.
_parse
()
self
.
_data
,
self
.
_files
=
self
.
_parse
()
def
_parse
(
self
):
def
_parse
(
self
):
"""
"""
Parse the request content
.
Parse the request content
, returning a two-tuple of (data, files)
May raise an `UnsupportedMediaType`, or `ParseError` exception.
May raise an `UnsupportedMediaType`, or `ParseError` exception.
"""
"""
...
@@ -214,8 +214,14 @@ class Request(object):
...
@@ -214,8 +214,14 @@ class Request(object):
for
parser
in
self
.
get_parsers
():
for
parser
in
self
.
get_parsers
():
if
parser
.
can_handle_request
(
self
.
content_type
):
if
parser
.
can_handle_request
(
self
.
content_type
):
return
parser
.
parse
(
self
.
stream
,
meta
=
self
.
META
,
parsed
=
parser
.
parse
(
self
.
stream
,
meta
=
self
.
META
,
upload_handlers
=
self
.
upload_handlers
)
upload_handlers
=
self
.
upload_handlers
)
# Parser classes may return the raw data, or a
# DataAndFiles object. Unpack the result as required.
try
:
return
(
parsed
.
data
,
parsed
.
files
)
except
AttributeError
:
return
(
parsed
,
None
)
raise
UnsupportedMediaType
(
self
.
_content_type
)
raise
UnsupportedMediaType
(
self
.
_content_type
)
...
...
djangorestframework/tests/parsers.py
View file @
7abef9ac
...
@@ -153,7 +153,7 @@ class TestFormParser(TestCase):
...
@@ -153,7 +153,7 @@ class TestFormParser(TestCase):
parser
=
FormParser
()
parser
=
FormParser
()
stream
=
StringIO
(
self
.
string
)
stream
=
StringIO
(
self
.
string
)
(
data
,
files
)
=
parser
.
parse
(
stream
)
data
=
parser
.
parse
(
stream
)
self
.
assertEqual
(
Form
(
data
)
.
is_valid
(),
True
)
self
.
assertEqual
(
Form
(
data
)
.
is_valid
(),
True
)
...
@@ -203,10 +203,10 @@ class TestXMLParser(TestCase):
...
@@ -203,10 +203,10 @@ class TestXMLParser(TestCase):
def
test_parse
(
self
):
def
test_parse
(
self
):
parser
=
XMLParser
()
parser
=
XMLParser
()
(
data
,
files
)
=
parser
.
parse
(
self
.
_input
)
data
=
parser
.
parse
(
self
.
_input
)
self
.
assertEqual
(
data
,
self
.
_data
)
self
.
assertEqual
(
data
,
self
.
_data
)
def
test_complex_data_parse
(
self
):
def
test_complex_data_parse
(
self
):
parser
=
XMLParser
()
parser
=
XMLParser
()
(
data
,
files
)
=
parser
.
parse
(
self
.
_complex_data_input
)
data
=
parser
.
parse
(
self
.
_complex_data_input
)
self
.
assertEqual
(
data
,
self
.
_complex_data
)
self
.
assertEqual
(
data
,
self
.
_complex_data
)
djangorestframework/tests/renderers.py
View file @
7abef9ac
...
@@ -301,7 +301,7 @@ if YAMLRenderer:
...
@@ -301,7 +301,7 @@ if YAMLRenderer:
parser
=
YAMLParser
()
parser
=
YAMLParser
()
content
=
renderer
.
render
(
obj
,
'application/yaml'
)
content
=
renderer
.
render
(
obj
,
'application/yaml'
)
(
data
,
files
)
=
parser
.
parse
(
StringIO
(
content
))
data
=
parser
.
parse
(
StringIO
(
content
))
self
.
assertEquals
(
obj
,
data
)
self
.
assertEquals
(
obj
,
data
)
...
@@ -392,7 +392,7 @@ class XMLRendererTestCase(TestCase):
...
@@ -392,7 +392,7 @@ class XMLRendererTestCase(TestCase):
content
=
StringIO
(
renderer
.
render
(
self
.
_complex_data
,
'application/xml'
))
content
=
StringIO
(
renderer
.
render
(
self
.
_complex_data
,
'application/xml'
))
parser
=
XMLParser
()
parser
=
XMLParser
()
complex_data_out
,
dummy
=
parser
.
parse
(
content
)
complex_data_out
=
parser
.
parse
(
content
)
error_msg
=
"complex data differs!IN:
\n
%
s
\n\n
OUT:
\n
%
s"
%
(
repr
(
self
.
_complex_data
),
repr
(
complex_data_out
))
error_msg
=
"complex data differs!IN:
\n
%
s
\n\n
OUT:
\n
%
s"
%
(
repr
(
self
.
_complex_data
),
repr
(
complex_data_out
))
self
.
assertEqual
(
self
.
_complex_data
,
complex_data_out
,
error_msg
)
self
.
assertEqual
(
self
.
_complex_data
,
complex_data_out
,
error_msg
)
...
...
djangorestframework/tests/request.py
View file @
7abef9ac
...
@@ -4,7 +4,6 @@ Tests for content parsing, and form-overloaded content parsing.
...
@@ -4,7 +4,6 @@ Tests for content parsing, and form-overloaded content parsing.
from
django.conf.urls.defaults
import
patterns
from
django.conf.urls.defaults
import
patterns
from
django.contrib.auth.models
import
User
from
django.contrib.auth.models
import
User
from
django.test
import
TestCase
,
Client
from
django.test
import
TestCase
,
Client
from
django.utils
import
simplejson
as
json
from
djangorestframework
import
status
from
djangorestframework
import
status
from
djangorestframework.authentication
import
UserLoggedInAuthentication
from
djangorestframework.authentication
import
UserLoggedInAuthentication
...
@@ -13,7 +12,6 @@ from djangorestframework.parsers import (
...
@@ -13,7 +12,6 @@ from djangorestframework.parsers import (
FormParser
,
FormParser
,
MultiPartParser
,
MultiPartParser
,
PlainTextParser
,
PlainTextParser
,
JSONParser
)
)
from
djangorestframework.request
import
Request
from
djangorestframework.request
import
Request
from
djangorestframework.response
import
Response
from
djangorestframework.response
import
Response
...
...
djangorestframework/utils/encoders.py
View file @
7abef9ac
"""
Helper classes for parsers.
"""
import
datetime
import
datetime
import
decimal
import
decimal
from
django.utils
import
timezone
from
django.utils
import
timezone
...
@@ -6,10 +9,12 @@ from django.utils import simplejson as json
...
@@ -6,10 +9,12 @@ from django.utils import simplejson as json
class
JSONEncoder
(
json
.
JSONEncoder
):
class
JSONEncoder
(
json
.
JSONEncoder
):
"""
"""
JSONEncoder subclass that knows how to encode date/time and decimal types.
JSONEncoder subclass that knows how to encode date/time,
decimal types, and generators.
"""
"""
def
default
(
self
,
o
):
def
default
(
self
,
o
):
# See "Date Time String Format" in the ECMA-262 specification.
# For Date Time string spec, see ECMA 262
# http://ecma-international.org/ecma-262/5.1/#sec-15.9.1.15
if
isinstance
(
o
,
datetime
.
datetime
):
if
isinstance
(
o
,
datetime
.
datetime
):
r
=
o
.
isoformat
()
r
=
o
.
isoformat
()
if
o
.
microsecond
:
if
o
.
microsecond
:
...
...
docs/tutorial/1-serialization.md
View file @
7abef9ac
...
@@ -127,7 +127,7 @@ We've now got a few comment instances to play with. Let's take a look at serial
...
@@ -127,7 +127,7 @@ We've now got a few comment instances to play with. Let's take a look at serial
serializer = CommentSerializer(instance=c1)
serializer = CommentSerializer(instance=c1)
serializer.data
serializer.data
# {'email': u'leila@example.com', 'content': u'nothing to say', 'created': datetime.datetime(2012, 8, 22, 16, 20, 9, 822774)}
# {'email': u'leila@example.com', 'content': u'nothing to say', 'created': datetime.datetime(2012, 8, 22, 16, 20, 9, 822774
, tzinfo=<UTC>
)}
At this point we've translated the model instance into python native datatypes. To finalise the serialization process we render the data into
`json`
.
At this point we've translated the model instance into python native datatypes. To finalise the serialization process we render the data into
`json`
.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment