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
b5b231a8
Commit
b5b231a8
authored
May 12, 2011
by
Tom Christie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
yet more API cleanup
parent
15f9e7c5
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
117 additions
and
122 deletions
+117
-122
djangorestframework/mixins.py
+56
-66
djangorestframework/renderers.py
+42
-37
djangorestframework/templates/renderer.html
+9
-9
djangorestframework/tests/accept.py
+2
-2
djangorestframework/tests/files.py
+1
-1
djangorestframework/tests/validators.py
+1
-1
djangorestframework/views.py
+6
-6
No files found.
djangorestframework/mixins.py
View file @
b5b231a8
...
@@ -48,23 +48,18 @@ class RequestMixin(object):
...
@@ -48,23 +48,18 @@ class RequestMixin(object):
parsers
=
()
parsers
=
()
def
_get_method
(
self
):
@property
def
method
(
self
):
"""
"""
Returns the HTTP method
for the current view
.
Returns the HTTP method.
"""
"""
if
not
hasattr
(
self
,
'_method'
):
if
not
hasattr
(
self
,
'_method'
):
self
.
_method
=
self
.
request
.
method
self
.
_method
=
self
.
request
.
method
return
self
.
_method
return
self
.
_method
def
_set_method
(
self
,
method
):
@property
"""
def
content_type
(
self
):
Set the method for the current view.
"""
self
.
_method
=
method
def
_get_content_type
(
self
):
"""
"""
Returns the content type header.
Returns the content type header.
"""
"""
...
@@ -73,11 +68,32 @@ class RequestMixin(object):
...
@@ -73,11 +68,32 @@ class RequestMixin(object):
return
self
.
_content_type
return
self
.
_content_type
def
_set_content_type
(
self
,
content_type
):
@property
def
DATA
(
self
):
"""
"""
Set the content type header
.
Returns the request data
.
"""
"""
self
.
_content_type
=
content_type
if
not
hasattr
(
self
,
'_data'
):
self
.
_load_data_and_files
()
return
self
.
_data
@property
def
FILES
(
self
):
"""
Returns the request files.
"""
if
not
hasattr
(
self
,
'_files'
):
self
.
_load_data_and_files
()
return
self
.
_files
def
_load_data_and_files
(
self
):
"""
Parse the request content into self.DATA and self.FILES.
"""
stream
=
self
.
_get_stream
()
(
self
.
_data
,
self
.
_files
)
=
self
.
_parse
(
stream
,
self
.
content_type
)
def
_get_stream
(
self
):
def
_get_stream
(
self
):
...
@@ -134,27 +150,6 @@ class RequestMixin(object):
...
@@ -134,27 +150,6 @@ class RequestMixin(object):
return
self
.
_stream
return
self
.
_stream
def
_set_stream
(
self
,
stream
):
"""
Set the stream representing the request body.
"""
self
.
_stream
=
stream
def
_load_data_and_files
(
self
):
(
self
.
_data
,
self
.
_files
)
=
self
.
_parse
(
self
.
stream
,
self
.
content_type
)
def
_get_data
(
self
):
if
not
hasattr
(
self
,
'_data'
):
self
.
_load_data_and_files
()
return
self
.
_data
def
_get_files
(
self
):
if
not
hasattr
(
self
,
'_files'
):
self
.
_load_data_and_files
()
return
self
.
_files
# TODO: Modify this so that it happens implictly, rather than being called explicitly
# TODO: Modify this so that it happens implictly, rather than being called explicitly
# ie accessing any of .DATA, .FILES, .content_type, .method will force
# ie accessing any of .DATA, .FILES, .content_type, .method will force
# form overloading.
# form overloading.
...
@@ -164,7 +159,10 @@ class RequestMixin(object):
...
@@ -164,7 +159,10 @@ class RequestMixin(object):
If it is then alter self.method, self.content_type, self.CONTENT to reflect that rather than simply
If it is then alter self.method, self.content_type, self.CONTENT to reflect that rather than simply
delegating them to the original request.
delegating them to the original request.
"""
"""
if
not
self
.
_USE_FORM_OVERLOADING
or
self
.
method
!=
'POST'
or
not
is_form_media_type
(
self
.
content_type
):
# We only need to use form overloading on form POST requests
content_type
=
self
.
request
.
META
.
get
(
'HTTP_CONTENT_TYPE'
,
self
.
request
.
META
.
get
(
'CONTENT_TYPE'
,
''
))
if
not
self
.
_USE_FORM_OVERLOADING
or
self
.
request
.
method
!=
'POST'
or
not
not
is_form_media_type
(
content_type
):
return
return
# Temporarily switch to using the form parsers, then parse the content
# Temporarily switch to using the form parsers, then parse the content
...
@@ -175,7 +173,7 @@ class RequestMixin(object):
...
@@ -175,7 +173,7 @@ class RequestMixin(object):
# Method overloading - change the method and remove the param from the content
# Method overloading - change the method and remove the param from the content
if
self
.
_METHOD_PARAM
in
content
:
if
self
.
_METHOD_PARAM
in
content
:
self
.
method
=
content
[
self
.
_METHOD_PARAM
]
.
upper
()
self
.
_
method
=
content
[
self
.
_METHOD_PARAM
]
.
upper
()
del
self
.
_data
[
self
.
_METHOD_PARAM
]
del
self
.
_data
[
self
.
_METHOD_PARAM
]
# Content overloading - rewind the stream and modify the content type
# Content overloading - rewind the stream and modify the content type
...
@@ -207,28 +205,21 @@ class RequestMixin(object):
...
@@ -207,28 +205,21 @@ class RequestMixin(object):
@property
@property
def
parsed_media_types
(
self
):
def
_
parsed_media_types
(
self
):
"""
"""
Return a
n
list of all the media types that this view can parse.
Return a list of all the media types that this view can parse.
"""
"""
return
[
parser
.
media_type
for
parser
in
self
.
parsers
]
return
[
parser
.
media_type
for
parser
in
self
.
parsers
]
@property
@property
def
default_parser
(
self
):
def
_
default_parser
(
self
):
"""
"""
Return the view's most preferred parser.
Return the view's default parser.
(This has no behavioral effect, but is may be used by documenting renderers)
"""
"""
return
self
.
parsers
[
0
]
return
self
.
parsers
[
0
]
method
=
property
(
_get_method
,
_set_method
)
content_type
=
property
(
_get_content_type
,
_set_content_type
)
stream
=
property
(
_get_stream
,
_set_stream
)
DATA
=
property
(
_get_data
)
FILES
=
property
(
_get_files
)
########## ResponseMixin ##########
########## ResponseMixin ##########
...
@@ -240,8 +231,9 @@ class ResponseMixin(object):
...
@@ -240,8 +231,9 @@ class ResponseMixin(object):
Also supports overriding the content type by specifying an _accept= parameter in the URL.
Also supports overriding the content type by specifying an _accept= parameter in the URL.
Ignores Accept headers from Internet Explorer user agents and uses a sensible browser Accept header instead.
Ignores Accept headers from Internet Explorer user agents and uses a sensible browser Accept header instead.
"""
"""
ACCEPT_QUERY_PARAM
=
'_accept'
# Allow override of Accept header in URL query params
REWRITE_IE_ACCEPT_HEADER
=
True
_ACCEPT_QUERY_PARAM
=
'_accept'
# Allow override of Accept header in URL query params
_IGNORE_IE_ACCEPT_HEADER
=
True
renderers
=
()
renderers
=
()
...
@@ -256,7 +248,7 @@ class ResponseMixin(object):
...
@@ -256,7 +248,7 @@ class ResponseMixin(object):
try
:
try
:
renderer
=
self
.
_determine_renderer
(
self
.
request
)
renderer
=
self
.
_determine_renderer
(
self
.
request
)
except
ErrorResponse
,
exc
:
except
ErrorResponse
,
exc
:
renderer
=
self
.
default_renderer
renderer
=
self
.
_
default_renderer
response
=
exc
.
response
response
=
exc
.
response
# Serialize the response content
# Serialize the response content
...
@@ -287,10 +279,10 @@ class ResponseMixin(object):
...
@@ -287,10 +279,10 @@ class ResponseMixin(object):
See: RFC 2616, Section 14 - http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
See: RFC 2616, Section 14 - http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
"""
"""
if
self
.
ACCEPT_QUERY_PARAM
and
request
.
GET
.
get
(
self
.
ACCEPT_QUERY_PARAM
,
None
):
if
self
.
_ACCEPT_QUERY_PARAM
and
request
.
GET
.
get
(
self
.
_
ACCEPT_QUERY_PARAM
,
None
):
# Use _accept parameter override
# Use _accept parameter override
accept_list
=
[
request
.
GET
.
get
(
self
.
ACCEPT_QUERY_PARAM
)]
accept_list
=
[
request
.
GET
.
get
(
self
.
_
ACCEPT_QUERY_PARAM
)]
elif
(
self
.
REWRIT
E_IE_ACCEPT_HEADER
and
elif
(
self
.
_IGNOR
E_IE_ACCEPT_HEADER
and
request
.
META
.
has_key
(
'HTTP_USER_AGENT'
)
and
request
.
META
.
has_key
(
'HTTP_USER_AGENT'
)
and
MSIE_USER_AGENT_REGEX
.
match
(
request
.
META
[
'HTTP_USER_AGENT'
])):
MSIE_USER_AGENT_REGEX
.
match
(
request
.
META
[
'HTTP_USER_AGENT'
])):
accept_list
=
[
'text/html'
,
'*/*'
]
accept_list
=
[
'text/html'
,
'*/*'
]
...
@@ -299,7 +291,7 @@ class ResponseMixin(object):
...
@@ -299,7 +291,7 @@ class ResponseMixin(object):
accept_list
=
request
.
META
[
"HTTP_ACCEPT"
]
.
split
(
','
)
accept_list
=
request
.
META
[
"HTTP_ACCEPT"
]
.
split
(
','
)
else
:
else
:
# No accept header specified
# No accept header specified
return
self
.
default_renderer
return
self
.
_
default_renderer
# Parse the accept header into a dict of {qvalue: set of media types}
# Parse the accept header into a dict of {qvalue: set of media types}
# We ignore mietype parameters
# We ignore mietype parameters
...
@@ -340,25 +332,24 @@ class ResponseMixin(object):
...
@@ -340,25 +332,24 @@ class ResponseMixin(object):
# Return default
# Return default
if
'*/*'
in
accept_set
:
if
'*/*'
in
accept_set
:
return
self
.
default_renderer
return
self
.
_
default_renderer
raise
ErrorResponse
(
status
.
HTTP_406_NOT_ACCEPTABLE
,
raise
ErrorResponse
(
status
.
HTTP_406_NOT_ACCEPTABLE
,
{
'detail'
:
'Could not satisfy the client
\'
s Accept header'
,
{
'detail'
:
'Could not satisfy the client
\'
s Accept header'
,
'available_types'
:
self
.
rendered_media_types
})
'available_types'
:
self
.
_
rendered_media_types
})
@property
@property
def
rendered_media_types
(
self
):
def
_
rendered_media_types
(
self
):
"""
"""
Return an list of all the media types that this
resource
can render.
Return an list of all the media types that this
view
can render.
"""
"""
return
[
renderer
.
media_type
for
renderer
in
self
.
renderers
]
return
[
renderer
.
media_type
for
renderer
in
self
.
renderers
]
@property
@property
def
default_renderer
(
self
):
def
_
default_renderer
(
self
):
"""
"""
Return the resource's most preferred renderer.
Return the view's default renderer.
(This renderer is used if the client does not send and Accept: header, or sends Accept: */*)
"""
"""
return
self
.
renderers
[
0
]
return
self
.
renderers
[
0
]
...
@@ -367,8 +358,7 @@ class ResponseMixin(object):
...
@@ -367,8 +358,7 @@ class ResponseMixin(object):
class
AuthMixin
(
object
):
class
AuthMixin
(
object
):
"""
"""
Simple mixin class to provide authentication and permission checking,
Simple mixin class to add authentication and permission checking to a ``View`` class.
by adding a set of authentication and permission classes on a ``View``.
"""
"""
authentication
=
()
authentication
=
()
permissions
=
()
permissions
=
()
...
@@ -408,12 +398,12 @@ class ResourceMixin(object):
...
@@ -408,12 +398,12 @@ class ResourceMixin(object):
@property
@property
def
CONTENT
(
self
):
def
CONTENT
(
self
):
if
not
hasattr
(
self
,
'_content'
):
if
not
hasattr
(
self
,
'_content'
):
self
.
_content
=
self
.
_get_content
(
self
.
DATA
,
self
.
FILES
)
self
.
_content
=
self
.
_get_content
()
return
self
.
_content
return
self
.
_content
def
_get_content
(
self
,
data
,
files
):
def
_get_content
(
self
):
resource
=
self
.
resource
(
self
)
resource
=
self
.
resource
(
self
)
return
resource
.
validate
(
data
,
files
)
return
resource
.
validate
(
self
.
DATA
,
self
.
FILES
)
def
get_bound_form
(
self
,
content
=
None
):
def
get_bound_form
(
self
,
content
=
None
):
resource
=
self
.
resource
(
self
)
resource
=
self
.
resource
(
self
)
...
...
djangorestframework/renderers.py
View file @
b5b231a8
...
@@ -52,7 +52,7 @@ class BaseRenderer(object):
...
@@ -52,7 +52,7 @@ class BaseRenderer(object):
should render the output.
should render the output.
EG: 'application/json; indent=4'
EG: 'application/json; indent=4'
By default render simply returns the ouput as-is.
By default render simply returns the ou
t
put as-is.
Override this method to provide for other behavior.
Override this method to provide for other behavior.
"""
"""
if
obj
is
None
:
if
obj
is
None
:
...
@@ -61,6 +61,41 @@ class BaseRenderer(object):
...
@@ -61,6 +61,41 @@ class BaseRenderer(object):
return
str
(
obj
)
return
str
(
obj
)
class
JSONRenderer
(
BaseRenderer
):
"""
Renderer which serializes to JSON
"""
media_type
=
'application/json'
def
render
(
self
,
obj
=
None
,
media_type
=
None
):
if
obj
is
None
:
return
''
# If the media type looks like 'application/json; indent=4', then
# pretty print the result.
indent
=
get_media_type_params
(
media_type
)
.
get
(
'indent'
,
None
)
sort_keys
=
False
try
:
indent
=
max
(
min
(
int
(
indent
),
8
),
0
)
sort_keys
=
True
except
(
ValueError
,
TypeError
):
indent
=
None
return
json
.
dumps
(
obj
,
indent
=
indent
,
sort_keys
=
sort_keys
)
class
XMLRenderer
(
BaseRenderer
):
"""
Renderer which serializes to XML.
"""
media_type
=
'application/xml'
def
render
(
self
,
obj
=
None
,
media_type
=
None
):
if
obj
is
None
:
return
''
return
dict2xml
(
obj
)
class
TemplateRenderer
(
BaseRenderer
):
class
TemplateRenderer
(
BaseRenderer
):
"""
"""
A Base class provided for convenience.
A Base class provided for convenience.
...
@@ -161,8 +196,8 @@ class DocumentingTemplateRenderer(BaseRenderer):
...
@@ -161,8 +196,8 @@ class DocumentingTemplateRenderer(BaseRenderer):
Add the fields dynamically."""
Add the fields dynamically."""
super
(
GenericContentForm
,
self
)
.
__init__
()
super
(
GenericContentForm
,
self
)
.
__init__
()
contenttype_choices
=
[(
media_type
,
media_type
)
for
media_type
in
view
.
parsed_media_types
]
contenttype_choices
=
[(
media_type
,
media_type
)
for
media_type
in
view
.
_
parsed_media_types
]
initial_contenttype
=
view
.
default_parser
.
media_type
initial_contenttype
=
view
.
_
default_parser
.
media_type
self
.
fields
[
view
.
_CONTENTTYPE_PARAM
]
=
forms
.
ChoiceField
(
label
=
'Content Type'
,
self
.
fields
[
view
.
_CONTENTTYPE_PARAM
]
=
forms
.
ChoiceField
(
label
=
'Content Type'
,
choices
=
contenttype_choices
,
choices
=
contenttype_choices
,
...
@@ -204,16 +239,19 @@ class DocumentingTemplateRenderer(BaseRenderer):
...
@@ -204,16 +239,19 @@ class DocumentingTemplateRenderer(BaseRenderer):
template
=
loader
.
get_template
(
self
.
template
)
template
=
loader
.
get_template
(
self
.
template
)
context
=
RequestContext
(
self
.
view
.
request
,
{
context
=
RequestContext
(
self
.
view
.
request
,
{
'content'
:
content
,
'content'
:
content
,
'
resource'
:
self
.
view
,
# TODO: rename to view
'
view'
:
self
.
view
,
'request'
:
self
.
view
.
request
,
# TODO: remove
'request'
:
self
.
view
.
request
,
# TODO: remove
'response'
:
self
.
view
.
response
,
'response'
:
self
.
view
.
response
,
'description'
:
description
,
'description'
:
description
,
'name'
:
name
,
'name'
:
name
,
'markeddown'
:
markeddown
,
'markeddown'
:
markeddown
,
'breadcrumblist'
:
breadcrumb_list
,
'breadcrumblist'
:
breadcrumb_list
,
'available_media_types'
:
self
.
view
.
_rendered_media_types
,
'form'
:
form_instance
,
'form'
:
form_instance
,
'login_url'
:
login_url
,
'login_url'
:
login_url
,
'logout_url'
:
logout_url
,
'logout_url'
:
logout_url
,
'ACCEPT_PARAM'
:
self
.
view
.
_ACCEPT_QUERY_PARAM
,
'METHOD_PARAM'
:
self
.
view
.
_METHOD_PARAM
,
'ADMIN_MEDIA_PREFIX'
:
settings
.
ADMIN_MEDIA_PREFIX
'ADMIN_MEDIA_PREFIX'
:
settings
.
ADMIN_MEDIA_PREFIX
})
})
...
@@ -228,39 +266,6 @@ class DocumentingTemplateRenderer(BaseRenderer):
...
@@ -228,39 +266,6 @@ class DocumentingTemplateRenderer(BaseRenderer):
return
ret
return
ret
class
JSONRenderer
(
BaseRenderer
):
"""
Renderer which serializes to JSON
"""
media_type
=
'application/json'
def
render
(
self
,
obj
=
None
,
media_type
=
None
):
if
obj
is
None
:
return
''
indent
=
get_media_type_params
(
media_type
)
.
get
(
'indent'
,
None
)
if
indent
is
not
None
:
try
:
indent
=
int
(
indent
)
except
ValueError
:
indent
=
None
sort_keys
=
indent
and
True
or
False
return
json
.
dumps
(
obj
,
indent
=
indent
,
sort_keys
=
sort_keys
)
class
XMLRenderer
(
BaseRenderer
):
"""
Renderer which serializes to XML.
"""
media_type
=
'application/xml'
def
render
(
self
,
obj
=
None
,
media_type
=
None
):
if
obj
is
None
:
return
''
return
dict2xml
(
obj
)
class
DocumentingHTMLRenderer
(
DocumentingTemplateRenderer
):
class
DocumentingHTMLRenderer
(
DocumentingTemplateRenderer
):
"""
"""
Renderer which provides a browsable HTML interface for an API.
Renderer which provides a browsable HTML interface for an API.
...
...
djangorestframework/templates/renderer.html
View file @
b5b231a8
...
@@ -42,14 +42,14 @@
...
@@ -42,14 +42,14 @@
{% endfor %}
{% endfor %}
{{ content|urlize_quoted_links }}
</pre>
{% endautoescape %}
</div>
{{ content|urlize_quoted_links }}
</pre>
{% endautoescape %}
</div>
{% if 'GET' in
resource
.allowed_methods %}
{% if 'GET' in
view
.allowed_methods %}
<form>
<form>
<fieldset
class=
'module aligned'
>
<fieldset
class=
'module aligned'
>
<h2>
GET {{ name }}
</h2>
<h2>
GET {{ name }}
</h2>
<div
class=
'submit-row'
style=
'margin: 0; border: 0'
>
<div
class=
'submit-row'
style=
'margin: 0; border: 0'
>
<a
href=
'{{ request.path }}'
rel=
"nofollow"
style=
'float: left'
>
GET
</a>
<a
href=
'{{ request.path }}'
rel=
"nofollow"
style=
'float: left'
>
GET
</a>
{% for media_type in
resource.rendered
_media_types %}
{% for media_type in
available
_media_types %}
{% with
resource.ACCEPT_QUERY
_PARAM|add:"="|add:media_type as param %}
{% with
ACCEPT
_PARAM|add:"="|add:media_type as param %}
[
<a
href=
'{{ request.path|add_query_param:param }}'
rel=
"nofollow"
>
{{ media_type }}
</a>
]
[
<a
href=
'{{ request.path|add_query_param:param }}'
rel=
"nofollow"
>
{{ media_type }}
</a>
]
{% endwith %}
{% endwith %}
{% endfor %}
{% endfor %}
...
@@ -63,8 +63,8 @@
...
@@ -63,8 +63,8 @@
*** (We could display only the POST form if method tunneling is disabled, but I think ***
*** (We could display only the POST form if method tunneling is disabled, but I think ***
*** the user experience would be confusing, so we simply turn all forms off. *** {% endcomment %}
*** the user experience would be confusing, so we simply turn all forms off. *** {% endcomment %}
{% if
resource.
METHOD_PARAM and form %}
{% if METHOD_PARAM and form %}
{% if 'POST' in
resource
.allowed_methods %}
{% if 'POST' in
view
.allowed_methods %}
<form
action=
"{{ request.path }}"
method=
"post"
{%
if
form
.
is_multipart
%}
enctype=
"multipart/form-data"
{%
endif
%}
>
<form
action=
"{{ request.path }}"
method=
"post"
{%
if
form
.
is_multipart
%}
enctype=
"multipart/form-data"
{%
endif
%}
>
<fieldset
class=
'module aligned'
>
<fieldset
class=
'module aligned'
>
<h2>
POST {{ name }}
</h2>
<h2>
POST {{ name }}
</h2>
...
@@ -85,11 +85,11 @@
...
@@ -85,11 +85,11 @@
</form>
</form>
{% endif %}
{% endif %}
{% if 'PUT' in
resource
.allowed_methods %}
{% if 'PUT' in
view
.allowed_methods %}
<form
action=
"{{ request.path }}"
method=
"post"
{%
if
form
.
is_multipart
%}
enctype=
"multipart/form-data"
{%
endif
%}
>
<form
action=
"{{ request.path }}"
method=
"post"
{%
if
form
.
is_multipart
%}
enctype=
"multipart/form-data"
{%
endif
%}
>
<fieldset
class=
'module aligned'
>
<fieldset
class=
'module aligned'
>
<h2>
PUT {{ name }}
</h2>
<h2>
PUT {{ name }}
</h2>
<input
type=
"hidden"
name=
"{{
resource.
METHOD_PARAM }}"
value=
"PUT"
/>
<input
type=
"hidden"
name=
"{{ METHOD_PARAM }}"
value=
"PUT"
/>
{% csrf_token %}
{% csrf_token %}
{{ form.non_field_errors }}
{{ form.non_field_errors }}
{% for field in form %}
{% for field in form %}
...
@@ -107,12 +107,12 @@
...
@@ -107,12 +107,12 @@
</form>
</form>
{% endif %}
{% endif %}
{% if 'DELETE' in
resource
.allowed_methods %}
{% if 'DELETE' in
view
.allowed_methods %}
<form
action=
"{{ request.path }}"
method=
"post"
>
<form
action=
"{{ request.path }}"
method=
"post"
>
<fieldset
class=
'module aligned'
>
<fieldset
class=
'module aligned'
>
<h2>
DELETE {{ name }}
</h2>
<h2>
DELETE {{ name }}
</h2>
{% csrf_token %}
{% csrf_token %}
<input
type=
"hidden"
name=
"{{
resource.
METHOD_PARAM }}"
value=
"DELETE"
/>
<input
type=
"hidden"
name=
"{{ METHOD_PARAM }}"
value=
"DELETE"
/>
<div
class=
'submit-row'
style=
'margin: 0; border: 0'
>
<div
class=
'submit-row'
style=
'margin: 0; border: 0'
>
<input
type=
"submit"
value=
"DELETE"
class=
"default"
/>
<input
type=
"submit"
value=
"DELETE"
class=
"default"
/>
</div>
</div>
...
...
djangorestframework/tests/accept.py
View file @
b5b231a8
...
@@ -40,9 +40,9 @@ class UserAgentMungingTest(TestCase):
...
@@ -40,9 +40,9 @@ class UserAgentMungingTest(TestCase):
self
.
assertEqual
(
resp
[
'Content-Type'
],
'text/html'
)
self
.
assertEqual
(
resp
[
'Content-Type'
],
'text/html'
)
def
test_dont_rewrite_msie_accept_header
(
self
):
def
test_dont_rewrite_msie_accept_header
(
self
):
"""Turn off
REWRIT
E_IE_ACCEPT_HEADER, send MSIE user agent strings and ensure
"""Turn off
_IGNOR
E_IE_ACCEPT_HEADER, send MSIE user agent strings and ensure
that we get a JSON response if we set a */* accept header."""
that we get a JSON response if we set a */* accept header."""
view
=
self
.
MockView
.
as_view
(
REWRIT
E_IE_ACCEPT_HEADER
=
False
)
view
=
self
.
MockView
.
as_view
(
_IGNOR
E_IE_ACCEPT_HEADER
=
False
)
for
user_agent
in
(
MSIE_9_USER_AGENT
,
for
user_agent
in
(
MSIE_9_USER_AGENT
,
MSIE_8_USER_AGENT
,
MSIE_8_USER_AGENT
,
...
...
djangorestframework/tests/files.py
View file @
b5b231a8
...
@@ -2,7 +2,7 @@ from django.test import TestCase
...
@@ -2,7 +2,7 @@ from django.test import TestCase
from
django
import
forms
from
django
import
forms
from
djangorestframework.compat
import
RequestFactory
from
djangorestframework.compat
import
RequestFactory
from
djangorestframework.views
import
BaseView
from
djangorestframework.views
import
BaseView
from
djangorestframework.resource
import
FormResource
from
djangorestframework.resource
s
import
FormResource
import
StringIO
import
StringIO
class
UploadFilesTests
(
TestCase
):
class
UploadFilesTests
(
TestCase
):
...
...
djangorestframework/tests/validators.py
View file @
b5b231a8
...
@@ -5,7 +5,7 @@ from djangorestframework.compat import RequestFactory
...
@@ -5,7 +5,7 @@ from djangorestframework.compat import RequestFactory
from
djangorestframework.validators
import
BaseValidator
,
FormValidator
,
ModelFormValidator
from
djangorestframework.validators
import
BaseValidator
,
FormValidator
,
ModelFormValidator
from
djangorestframework.response
import
ErrorResponse
from
djangorestframework.response
import
ErrorResponse
from
djangorestframework.views
import
BaseView
from
djangorestframework.views
import
BaseView
from
djangorestframework.resource
import
Resource
from
djangorestframework.resource
s
import
Resource
class
TestValidatorMixinInterfaces
(
TestCase
):
class
TestValidatorMixinInterfaces
(
TestCase
):
...
...
djangorestframework/views.py
View file @
b5b231a8
...
@@ -4,7 +4,7 @@ from django.views.decorators.csrf import csrf_exempt
...
@@ -4,7 +4,7 @@ from django.views.decorators.csrf import csrf_exempt
from
djangorestframework.compat
import
View
from
djangorestframework.compat
import
View
from
djangorestframework.response
import
Response
,
ErrorResponse
from
djangorestframework.response
import
Response
,
ErrorResponse
from
djangorestframework.mixins
import
*
from
djangorestframework.mixins
import
*
from
djangorestframework
import
resource
,
renderers
,
parsers
,
authentication
,
permissions
,
validator
s
,
status
from
djangorestframework
import
resource
s
,
renderers
,
parsers
,
authentication
,
permission
s
,
status
__all__
=
(
__all__
=
(
...
@@ -22,7 +22,7 @@ class BaseView(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, View):
...
@@ -22,7 +22,7 @@ class BaseView(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, View):
Performs request deserialization, response serialization, authentication and input validation."""
Performs request deserialization, response serialization, authentication and input validation."""
# Use the base resource by default
# Use the base resource by default
resource
=
resource
.
Resource
resource
=
resource
s
.
Resource
# List of renderers the resource can serialize the response with, ordered by preference.
# List of renderers the resource can serialize the response with, ordered by preference.
renderers
=
(
renderers
.
JSONRenderer
,
renderers
=
(
renderers
.
JSONRenderer
,
...
@@ -36,9 +36,6 @@ class BaseView(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, View):
...
@@ -36,9 +36,6 @@ class BaseView(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, View):
parsers
.
FormParser
,
parsers
.
FormParser
,
parsers
.
MultiPartParser
)
parsers
.
MultiPartParser
)
# List of validators to validate, cleanup and normalize the request content
validators
=
(
validators
.
FormValidator
,
)
# List of all authenticating methods to attempt.
# List of all authenticating methods to attempt.
authentication
=
(
authentication
.
UserLoggedInAuthenticaton
,
authentication
=
(
authentication
.
UserLoggedInAuthenticaton
,
authentication
.
BasicAuthenticaton
)
authentication
.
BasicAuthenticaton
)
...
@@ -54,6 +51,9 @@ class BaseView(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, View):
...
@@ -54,6 +51,9 @@ class BaseView(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, View):
@property
@property
def
allowed_methods
(
self
):
def
allowed_methods
(
self
):
"""
Return the list of allowed HTTP methods, uppercased.
"""
return
[
method
.
upper
()
for
method
in
self
.
http_method_names
if
hasattr
(
self
,
method
)]
return
[
method
.
upper
()
for
method
in
self
.
http_method_names
if
hasattr
(
self
,
method
)]
def
http_method_not_allowed
(
self
,
request
,
*
args
,
**
kwargs
):
def
http_method_not_allowed
(
self
,
request
,
*
args
,
**
kwargs
):
...
@@ -127,7 +127,7 @@ class BaseView(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, View):
...
@@ -127,7 +127,7 @@ class BaseView(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, View):
class
ModelView
(
BaseView
):
class
ModelView
(
BaseView
):
"""A RESTful view that maps to a model in the database."""
"""A RESTful view that maps to a model in the database."""
validators
=
(
validators
.
ModelFormValidator
,)
resource
=
resources
.
ModelResource
class
InstanceModelView
(
ReadModelMixin
,
UpdateModelMixin
,
DeleteModelMixin
,
ModelView
):
class
InstanceModelView
(
ReadModelMixin
,
UpdateModelMixin
,
DeleteModelMixin
,
ModelView
):
"""A view which provides default operations for read/update/delete against a model instance."""
"""A view which provides default operations for read/update/delete against a model instance."""
...
...
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