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
8c3280f9
Commit
8c3280f9
authored
May 19, 2011
by
Tom Christie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
data flattening needs to go into resource
parent
49d4e503
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
39 additions
and
78 deletions
+39
-78
djangorestframework/mixins.py
+1
-2
djangorestframework/parsers.py
+35
-74
djangorestframework/permissions.py
+1
-0
djangorestframework/tests/content.py
+1
-1
djangorestframework/tests/parsers.py
+0
-0
examples/modelresourceexample/urls.py
+1
-1
No files found.
djangorestframework/mixins.py
View file @
8c3280f9
...
@@ -26,7 +26,7 @@ __all__ = (
...
@@ -26,7 +26,7 @@ __all__ = (
'ResponseMixin'
,
'ResponseMixin'
,
'AuthMixin'
,
'AuthMixin'
,
'ResourceMixin'
,
'ResourceMixin'
,
#
#
Reverse URL lookup behavior
'InstanceMixin'
,
'InstanceMixin'
,
# Model behavior mixins
# Model behavior mixins
'ReadModelMixin'
,
'ReadModelMixin'
,
...
@@ -360,7 +360,6 @@ class AuthMixin(object):
...
@@ -360,7 +360,6 @@ class AuthMixin(object):
"""
"""
The set of authentication types that this view can handle.
The set of authentication types that this view can handle.
Should be a tuple/list of classes as described in the ``authentication`` module.
Should be a tuple/list of classes as described in the ``authentication`` module.
"""
"""
authentication
=
()
authentication
=
()
...
...
djangorestframework/parsers.py
View file @
8c3280f9
...
@@ -63,9 +63,18 @@ class BaseParser(object):
...
@@ -63,9 +63,18 @@ class BaseParser(object):
class
JSONParser
(
BaseParser
):
class
JSONParser
(
BaseParser
):
"""
JSON parser.
"""
media_type
=
'application/json'
media_type
=
'application/json'
def
parse
(
self
,
stream
):
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
:
try
:
return
(
json
.
load
(
stream
),
None
)
return
(
json
.
load
(
stream
),
None
)
except
ValueError
,
exc
:
except
ValueError
,
exc
:
...
@@ -73,103 +82,55 @@ class JSONParser(BaseParser):
...
@@ -73,103 +82,55 @@ class JSONParser(BaseParser):
{
'detail'
:
'JSON parse error -
%
s'
%
unicode
(
exc
)})
{
'detail'
:
'JSON parse error -
%
s'
%
unicode
(
exc
)})
class
DataFlatener
(
object
):
"""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
with information provided by the method "is_a_list"."""
flatdata
=
dict
()
for
key
,
val_list
in
data
.
items
():
if
self
.
is_a_list
(
key
,
val_list
):
flatdata
[
key
]
=
val_list
else
:
if
val_list
:
flatdata
[
key
]
=
val_list
[
0
]
else
:
# If the list is empty, but the parameter is not a list,
# we strip this parameter.
data
.
pop
(
key
)
return
flatdata
def
is_a_list
(
self
,
key
,
val_list
):
"""Returns True if the parameter with name *key* is expected to be a list, or False otherwise.
*val_list* which is the received value for parameter *key* can be used to guess the answer."""
return
False
class
PlainTextParser
(
BaseParser
):
class
PlainTextParser
(
BaseParser
):
"""
"""
Plain text parser.
Plain text parser.
Simply returns the content of the stream.
"""
"""
media_type
=
'text/plain'
media_type
=
'text/plain'
def
parse
(
self
,
stream
):
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
)
return
(
stream
.
read
(),
None
)
class
FormParser
(
BaseParser
,
DataFlatener
):
class
FormParser
(
BaseParser
):
"""
Parser for form data.
"""
"""
The default parser for form data.
Return a dict containing a single value for each non-reserved parameter.
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
=
'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.
A common hack to avoid this is to send the parameter with a value specifying that the list is empty.
This value will always be stripped before the data is returned.
"""
EMPTY_VALUE
=
'_empty'
RESERVED_FORM_PARAMS
=
(
'csrfmiddlewaretoken'
,)
def
parse
(
self
,
stream
):
def
parse
(
self
,
stream
):
"""
Returns a 2-tuple of `(data, files)`.
`data` will be a `QueryDict` containing all the form parameters.
`files` will always be `None`.
"""
data
=
parse_qs
(
stream
.
read
(),
keep_blank_values
=
True
)
data
=
parse_qs
(
stream
.
read
(),
keep_blank_values
=
True
)
# removing EMPTY_VALUEs from the lists and flatening the data
for
key
,
val_list
in
data
.
items
():
self
.
remove_empty_val
(
val_list
)
data
=
self
.
flatten_data
(
data
)
# Strip any parameters that we are treating as reserved
for
key
in
data
.
keys
():
if
key
in
self
.
RESERVED_FORM_PARAMS
:
data
.
pop
(
key
)
return
(
data
,
None
)
return
(
data
,
None
)
def
remove_empty_val
(
self
,
val_list
):
""" """
while
(
1
):
# Because there might be several times EMPTY_VALUE in the list
try
:
ind
=
val_list
.
index
(
self
.
EMPTY_VALUE
)
except
ValueError
:
break
else
:
val_list
.
pop
(
ind
)
class
MultiPartParser
(
BaseParser
):
"""
Parser for multipart form data, which may include file data.
"""
class
MultiPartParser
(
BaseParser
,
DataFlatener
):
media_type
=
'multipart/form-data'
media_type
=
'multipart/form-data'
RESERVED_FORM_PARAMS
=
(
'csrfmiddlewaretoken'
,)
def
parse
(
self
,
stream
):
def
parse
(
self
,
stream
):
"""
Returns a 2-tuple of `(data, files)`.
`data` will be a `QueryDict` containing all the form parameters.
`files` will be a `QueryDict` containing all the form files.
"""
upload_handlers
=
self
.
view
.
request
.
_get_upload_handlers
()
upload_handlers
=
self
.
view
.
request
.
_get_upload_handlers
()
django_parser
=
DjangoMultiPartParser
(
self
.
view
.
request
.
META
,
stream
,
upload_handlers
)
django_parser
=
DjangoMultiPartParser
(
self
.
view
.
request
.
META
,
stream
,
upload_handlers
)
data
,
files
=
django_parser
.
parse
()
return
django_parser
.
parse
()
# Flatening data, files and combining them
data
=
self
.
flatten_data
(
dict
(
data
.
iterlists
()))
files
=
self
.
flatten_data
(
dict
(
files
.
iterlists
()))
# Strip any parameters that we are treating as reserved
for
key
in
data
.
keys
():
if
key
in
self
.
RESERVED_FORM_PARAMS
:
data
.
pop
(
key
)
return
(
data
,
files
)
djangorestframework/permissions.py
View file @
8c3280f9
...
@@ -59,6 +59,7 @@ class IsAuthenticated(BasePermission):
...
@@ -59,6 +59,7 @@ class IsAuthenticated(BasePermission):
if
not
user
.
is_authenticated
():
if
not
user
.
is_authenticated
():
raise
_403_FORBIDDEN_RESPONSE
raise
_403_FORBIDDEN_RESPONSE
class
IsAdminUser
():
class
IsAdminUser
():
"""
"""
Allows access only to admin users.
Allows access only to admin users.
...
...
djangorestframework/tests/content.py
View file @
8c3280f9
...
@@ -36,7 +36,7 @@ class TestContentParsing(TestCase):
...
@@ -36,7 +36,7 @@ class TestContentParsing(TestCase):
form_data
=
{
'qwerty'
:
'uiop'
}
form_data
=
{
'qwerty'
:
'uiop'
}
view
.
parsers
=
(
FormParser
,
MultiPartParser
)
view
.
parsers
=
(
FormParser
,
MultiPartParser
)
view
.
request
=
self
.
req
.
put
(
'/'
,
data
=
form_data
)
view
.
request
=
self
.
req
.
put
(
'/'
,
data
=
form_data
)
self
.
assertEqual
(
view
.
DATA
,
form_data
)
self
.
assertEqual
(
view
.
DATA
.
items
(),
form_data
.
items
()
)
def
ensure_determines_non_form_content_PUT
(
self
,
view
):
def
ensure_determines_non_form_content_PUT
(
self
,
view
):
"""Ensure view.RAW_CONTENT returns content for PUT request with non-form content."""
"""Ensure view.RAW_CONTENT returns content for PUT request with non-form content."""
...
...
djangorestframework/tests/parsers.py
View file @
8c3280f9
This diff is collapsed.
Click to expand it.
examples/modelresourceexample/urls.py
View file @
8c3280f9
...
@@ -8,7 +8,7 @@ class MyModelResource(ModelResource):
...
@@ -8,7 +8,7 @@ class MyModelResource(ModelResource):
fields
=
(
'foo'
,
'bar'
,
'baz'
,
'url'
)
fields
=
(
'foo'
,
'bar'
,
'baz'
,
'url'
)
ordering
=
(
'created'
,)
ordering
=
(
'created'
,)
urlpatterns
=
patterns
(
'
modelresourceexample.views
'
,
urlpatterns
=
patterns
(
''
,
url
(
r'^$'
,
ListOrCreateModelView
.
as_view
(
resource
=
MyModelResource
),
name
=
'model-resource-root'
),
url
(
r'^$'
,
ListOrCreateModelView
.
as_view
(
resource
=
MyModelResource
),
name
=
'model-resource-root'
),
url
(
r'^([0-9]+)/$'
,
InstanceModelView
.
as_view
(
resource
=
MyModelResource
)),
url
(
r'^([0-9]+)/$'
,
InstanceModelView
.
as_view
(
resource
=
MyModelResource
)),
)
)
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