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
8457c871
Commit
8457c871
authored
Sep 04, 2012
by
Tom Christie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Bits of cleanup
parent
29dfbaba
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
98 additions
and
37 deletions
+98
-37
djangorestframework/authentication.py
+2
-2
djangorestframework/decorators.py
+12
-4
djangorestframework/mixins.py
+23
-2
djangorestframework/tests/request.py
+3
-3
djangorestframework/urls.py
+14
-0
djangorestframework/utils/mediatypes.py
+4
-4
djangorestframework/views.py
+40
-22
No files found.
djangorestframework/authentication.py
View file @
8457c871
...
...
@@ -11,7 +11,7 @@ import base64
__all__
=
(
'BaseAuthentication'
,
'BasicAuthentication'
,
'
UserLoggedI
nAuthentication'
'
Sessio
nAuthentication'
)
...
...
@@ -68,7 +68,7 @@ class BasicAuthentication(BaseAuthentication):
return
None
class
UserLoggedI
nAuthentication
(
BaseAuthentication
):
class
Sessio
nAuthentication
(
BaseAuthentication
):
"""
Use Django's session framework for authentication.
"""
...
...
djangorestframework/decorators.py
View file @
8457c871
...
...
@@ -10,14 +10,13 @@ from djangorestframework.request import Request
def
api_view
(
allowed_methods
):
"""
Decorator
to make a view only accept particular request methods. Usage::
Decorator
for function based views.
@api_view(['GET', 'POST'])
def my_view(request):
# request will be an instance of `Request`
# `Response` objects will have .request set automatically
# APIException instances will be handled
Note that request methods should be in uppercase.
"""
allowed_methods
=
[
method
.
upper
()
for
method
in
allowed_methods
]
...
...
@@ -25,17 +24,26 @@ def api_view(allowed_methods):
@wraps
(
func
,
assigned
=
available_attrs
(
func
))
def
inner
(
request
,
*
args
,
**
kwargs
):
try
:
request
=
Request
(
request
)
if
request
.
method
not
in
allowed_methods
:
return
exceptions
.
MethodNotAllowed
(
request
.
method
)
raise
exceptions
.
MethodNotAllowed
(
request
.
method
)
response
=
func
(
request
,
*
args
,
**
kwargs
)
if
isinstance
(
response
,
Response
):
response
.
request
=
request
return
response
except
exceptions
.
APIException
as
exc
:
return
Response
({
'detail'
:
exc
.
detail
},
status
=
exc
.
status_code
)
except
Http404
as
exc
:
return
Response
({
'detail'
:
'Not found'
},
status
=
status
.
HTTP_404_NOT_FOUND
)
except
PermissionDenied
as
exc
:
return
Response
({
'detail'
:
'Permission denied'
},
status
=
status
.
HTTP_403_FORBIDDEN
)
...
...
djangorestframework/mixins.py
View file @
8457c871
...
...
@@ -2,10 +2,31 @@ from djangorestframework import status
from
djangorestframework.response
import
Response
class
MetadataMixin
(
object
):
"""
Should be mixed in with any `BaseView`.
"""
def
metadata
(
self
,
request
,
*
args
,
**
kwargs
):
content
=
{
'name'
:
self
.
get_name
(),
'description'
:
self
.
get_description
(),
'renders'
:
self
.
_rendered_media_types
,
'parses'
:
self
.
_parsed_media_types
,
}
# TODO: Add 'fields', from serializer info.
# form = self.get_bound_form()
# if form is not None:
# field_name_types = {}
# for name, field in form.fields.iteritems():
# field_name_types[name] = field.__class__.__name__
# content['fields'] = field_name_types
raise
Response
(
content
,
status
=
status
.
HTTP_200_OK
)
class
CreateModelMixin
(
object
):
"""
Create a model instance.
Should be mixed in with any `
APIView`
Should be mixed in with any `
BaseView`.
"""
def
create
(
self
,
request
,
*
args
,
**
kwargs
):
serializer
=
self
.
get_serializer
(
data
=
request
.
DATA
)
...
...
@@ -47,7 +68,7 @@ class UpdateModelMixin(object):
self
.
object
=
self
.
get_object
()
serializer
=
self
.
get_serializer
(
data
=
request
.
DATA
,
instance
=
self
.
object
)
if
serializer
.
is_valid
():
self
.
object
=
serializer
.
deserialized
self
.
object
=
serializer
.
object
self
.
object
.
save
()
return
Response
(
serializer
.
data
)
return
Response
(
serializer
.
error_data
,
status
=
status
.
HTTP_400_BAD_REQUEST
)
...
...
djangorestframework/tests/request.py
View file @
8457c871
...
...
@@ -6,7 +6,7 @@ from django.contrib.auth.models import User
from
django.test
import
TestCase
,
Client
from
djangorestframework
import
status
from
djangorestframework.authentication
import
UserLoggedI
nAuthentication
from
djangorestframework.authentication
import
Sessio
nAuthentication
from
djangorestframework.utils
import
RequestFactory
from
djangorestframework.parsers
import
(
FormParser
,
...
...
@@ -208,7 +208,7 @@ class TestContentParsing(TestCase):
class
MockView
(
APIView
):
authentication
=
(
UserLoggedI
nAuthentication
,)
authentication
=
(
Sessio
nAuthentication
,)
def
post
(
self
,
request
):
if
request
.
POST
.
get
(
'example'
)
is
not
None
:
...
...
@@ -233,7 +233,7 @@ class TestContentParsingWithAuthentication(TestCase):
def
test_user_logged_in_authentication_has_POST_when_not_logged_in
(
self
):
"""
Ensures request.POST exists after
UserLoggedI
nAuthentication when user
Ensures request.POST exists after
Sessio
nAuthentication when user
doesn't log in.
"""
content
=
{
'example'
:
'example'
}
...
...
djangorestframework/urls.py
View file @
8457c871
"""
Login and logout views for the browseable API.
Add these to your root URLconf if you're using the browseable API and
your API requires authentication.
The urls must be namespaced as 'djangorestframework', and you should make sure
your authentication settings include `SessionAuthentication`.
urlpatterns = patterns('',
...
url(r'^auth', include('djangorestframework.urls', namespace='djangorestframework'))
)
"""
from
django.conf.urls.defaults
import
patterns
,
url
...
...
djangorestframework/utils/mediatypes.py
View file @
8457c871
...
...
@@ -53,7 +53,7 @@ def get_media_type_params(media_type):
def
order_by_precedence
(
media_type_lst
):
"""
Returns a list of
lis
ts of media type strings, ordered by precedence.
Returns a list of
se
ts of media type strings, ordered by precedence.
Precedence is determined by how specific a media type is:
3. 'type/subtype; param=val'
...
...
@@ -61,11 +61,11 @@ def order_by_precedence(media_type_lst):
1. 'type/*'
0. '*/*'
"""
ret
=
[
[],
[],
[],
[]
]
ret
=
[
set
(),
set
(),
set
(),
set
()
]
for
media_type
in
media_type_lst
:
precedence
=
_MediaType
(
media_type
)
.
precedence
ret
[
3
-
precedence
]
.
a
ppen
d
(
media_type
)
return
ret
ret
[
3
-
precedence
]
.
a
d
d
(
media_type
)
return
[
media_types
for
media_types
in
ret
if
media_types
]
class
_MediaType
(
object
):
...
...
djangorestframework/views.py
View file @
8457c871
...
...
@@ -80,7 +80,7 @@ class APIView(_View):
List of parser classes the view can parse the request with.
"""
authentication
=
(
authentication
.
UserLoggedI
nAuthentication
,
authentication
=
(
authentication
.
Sessio
nAuthentication
,
authentication
.
BasicAuthentication
)
"""
List of all authenticating methods to attempt.
...
...
@@ -217,11 +217,14 @@ class APIView(_View):
else in the view.
Returns the final response object.
"""
if
isinstance
(
response
,
Response
):
response
.
view
=
self
response
.
request
=
request
response
.
renderers
=
self
.
renderers
for
key
,
value
in
self
.
headers
.
items
():
response
[
key
]
=
value
return
response
def
handle_exception
(
self
,
exc
):
...
...
@@ -269,43 +272,43 @@ class APIView(_View):
self
.
response
=
self
.
final
(
request
,
response
,
*
args
,
**
kwargs
)
return
self
.
response
def
options
(
self
,
request
,
*
args
,
**
kwargs
):
content
=
{
'name'
:
self
.
get_name
(),
'description'
:
self
.
get_description
(),
'renders'
:
self
.
_rendered_media_types
,
'parses'
:
self
.
_parsed_media_types
,
}
form
=
self
.
get_bound_form
()
if
form
is
not
None
:
field_name_types
=
{}
for
name
,
field
in
form
.
fields
.
iteritems
():
field_name_types
[
name
]
=
field
.
__class__
.
__name__
content
[
'fields'
]
=
field_name_types
raise
Response
(
content
,
status
=
status
.
HTTP_200_OK
)
# TODO: .get_serializer()
# Abstract view classes that do not provide any method handlers,
# but which provide required behaviour for concrete views to build on.
class
BaseView
(
APIView
):
"""
Base class for all generic views.
"""
serializer_class
=
None
def
get_serializer
(
self
,
data
=
None
,
files
=
None
,
instance
=
None
):
context
=
{
'request'
:
self
.
request
,
'format'
:
self
.
kwargs
.
get
(
'format'
,
None
)
}
return
self
.
serializer_class
(
data
,
context
=
context
)
### Abstract view classes, that do not provide any method handlers ###
class
MultipleObjectBaseView
(
MultipleObjectMixin
,
API
View
):
class
MultipleObjectBaseView
(
MultipleObjectMixin
,
Base
View
):
"""
Base class for views onto a queryset.
Base class for
generic
views onto a queryset.
"""
pass
class
SingleObjectBaseView
(
SingleObjectMixin
,
API
View
):
class
SingleObjectBaseView
(
SingleObjectMixin
,
Base
View
):
"""
Base class for views onto a model instance.
Base class for
generic
views onto a model instance.
"""
pass
### Concrete view classes, that provide existing method handlers ###
# Concrete view classes that provide method handlers
# by composing the mixin classes with a base view.
class
ListAPIView
(
mixins
.
ListModelMixin
,
mixins
.
MetadataMixin
,
MultipleObjectBaseView
):
"""
Concrete view for listing a queryset.
...
...
@@ -313,9 +316,13 @@ class ListAPIView(mixins.ListModelMixin,
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
return
self
.
list
(
request
,
*
args
,
**
kwargs
)
def
options
(
self
,
request
,
*
args
,
**
kwargs
):
return
self
.
metadata
(
request
,
*
args
,
**
kwargs
)
class
RootAPIView
(
mixins
.
ListModelMixin
,
mixins
.
CreateModelMixin
,
mixins
.
MetadataMixin
,
MultipleObjectBaseView
):
"""
Concrete view for listing a queryset or creating a model instance.
...
...
@@ -326,8 +333,12 @@ class RootAPIView(mixins.ListModelMixin,
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
return
self
.
create
(
request
,
*
args
,
**
kwargs
)
def
options
(
self
,
request
,
*
args
,
**
kwargs
):
return
self
.
metadata
(
request
,
*
args
,
**
kwargs
)
class
DetailAPIView
(
mixins
.
RetrieveModelMixin
,
mixins
.
MetadataMixin
,
SingleObjectBaseView
):
"""
Concrete view for retrieving a model instance.
...
...
@@ -335,10 +346,14 @@ class DetailAPIView(mixins.RetrieveModelMixin,
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
return
self
.
retrieve
(
request
,
*
args
,
**
kwargs
)
def
options
(
self
,
request
,
*
args
,
**
kwargs
):
return
self
.
metadata
(
request
,
*
args
,
**
kwargs
)
class
InstanceAPIView
(
mixins
.
RetrieveModelMixin
,
mixins
.
UpdateModelMixin
,
mixins
.
DestroyModelMixin
,
mixins
.
MetadataMixin
,
SingleObjectBaseView
):
"""
Concrete view for retrieving, updating or deleting a model instance.
...
...
@@ -351,3 +366,6 @@ class InstanceAPIView(mixins.RetrieveModelMixin,
def
delete
(
self
,
request
,
*
args
,
**
kwargs
):
return
self
.
destroy
(
request
,
*
args
,
**
kwargs
)
def
options
(
self
,
request
,
*
args
,
**
kwargs
):
return
self
.
metadata
(
request
,
*
args
,
**
kwargs
)
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