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
f68721ad
Commit
f68721ad
authored
Apr 04, 2013
by
Tom Christie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Factor view names/descriptions out of View class
parent
9e24db02
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
117 additions
and
104 deletions
+117
-104
rest_framework/renderers.py
+3
-8
rest_framework/routers.py
+21
-13
rest_framework/utils/breadcrumbs.py
+3
-2
rest_framework/utils/formatting.py
+77
-0
rest_framework/views.py
+9
-80
rest_framework/viewsets.py
+4
-1
No files found.
rest_framework/renderers.py
View file @
f68721ad
...
@@ -24,6 +24,7 @@ from rest_framework.settings import api_settings
...
@@ -24,6 +24,7 @@ from rest_framework.settings import api_settings
from
rest_framework.request
import
clone_request
from
rest_framework.request
import
clone_request
from
rest_framework.utils
import
encoders
from
rest_framework.utils
import
encoders
from
rest_framework.utils.breadcrumbs
import
get_breadcrumbs
from
rest_framework.utils.breadcrumbs
import
get_breadcrumbs
from
rest_framework.utils.formatting
import
get_view_name
,
get_view_description
from
rest_framework
import
exceptions
,
parsers
,
status
,
VERSION
from
rest_framework
import
exceptions
,
parsers
,
status
,
VERSION
...
@@ -438,16 +439,10 @@ class BrowsableAPIRenderer(BaseRenderer):
...
@@ -438,16 +439,10 @@ class BrowsableAPIRenderer(BaseRenderer):
return
GenericContentForm
()
return
GenericContentForm
()
def
get_name
(
self
,
view
):
def
get_name
(
self
,
view
):
try
:
return
get_view_name
(
view
.
__class__
)
return
view
.
get_name
()
except
AttributeError
:
return
smart_text
(
view
.
__class__
.
__name__
)
def
get_description
(
self
,
view
):
def
get_description
(
self
,
view
):
try
:
return
get_view_description
(
view
.
__class__
,
html
=
True
)
return
view
.
get_description
(
html
=
True
)
except
AttributeError
:
return
smart_text
(
view
.
__doc__
or
''
)
def
render
(
self
,
data
,
accepted_media_type
=
None
,
renderer_context
=
None
):
def
render
(
self
,
data
,
accepted_media_type
=
None
,
renderer_context
=
None
):
"""
"""
...
...
rest_framework/routers.py
View file @
f68721ad
...
@@ -14,23 +14,31 @@ class BaseRouter(object):
...
@@ -14,23 +14,31 @@ class BaseRouter(object):
@property
@property
def
urlpatterns
(
self
):
def
urlpatterns
(
self
):
if
not
hasattr
(
self
,
'_urlpatterns'
):
if
not
hasattr
(
self
,
'_urlpatterns'
):
print
self
.
get_urlpatterns
()
self
.
_urlpatterns
=
patterns
(
''
,
*
self
.
get_urlpatterns
())
self
.
_urlpatterns
=
patterns
(
''
,
*
self
.
get_urlpatterns
())
return
self
.
_urlpatterns
return
self
.
_urlpatterns
class
DefaultRouter
(
BaseRouter
):
class
DefaultRouter
(
BaseRouter
):
route_list
=
[
route_list
=
[
(
r'$'
,
{
'get'
:
'list'
,
'post'
:
'create'
},
'
%
s-
list'
),
(
r'$'
,
{
'get'
:
'list'
,
'post'
:
'create'
},
'list'
),
(
r'(?P<pk>[^/]+)/$'
,
{
'get'
:
'retrieve'
,
'put'
:
'update'
,
'delete'
:
'destroy'
},
'
%
s-
detail'
),
(
r'(?P<pk>[^/]+)/$'
,
{
'get'
:
'retrieve'
,
'put'
:
'update'
,
'delete'
:
'destroy'
},
'detail'
),
]
]
extra_routes
=
(
r'(?P<pk>[^/]+)/
%
s/$'
,
'
%
s-
%
s'
)
extra_routes
=
r'(?P<pk>[^/]+)/
%
s/$'
name_format
=
'
%
s-
%
s'
def
get_urlpatterns
(
self
):
def
get_urlpatterns
(
self
):
ret
=
[]
ret
=
[]
for
prefix
,
viewset
,
base_name
in
self
.
registry
:
for
prefix
,
viewset
,
base_name
in
self
.
registry
:
# Bind regular views
if
not
getattr
(
viewset
,
'_is_viewset'
,
False
):
regex
=
prefix
view
=
viewset
name
=
base_name
ret
.
append
(
url
(
regex
,
view
,
name
=
name
))
continue
# Bind standard CRUD routes
# Bind standard CRUD routes
for
suffix
,
action_mapping
,
name_format
in
self
.
route_list
:
for
suffix
,
action_mapping
,
action_name
in
self
.
route_list
:
# Only actions which actually exist on the viewset will be bound
# Only actions which actually exist on the viewset will be bound
bound_actions
=
{}
bound_actions
=
{}
...
@@ -40,25 +48,25 @@ class DefaultRouter(BaseRouter):
...
@@ -40,25 +48,25 @@ class DefaultRouter(BaseRouter):
# Build the url pattern
# Build the url pattern
regex
=
prefix
+
suffix
regex
=
prefix
+
suffix
view
=
viewset
.
as_view
(
bound_actions
)
view
=
viewset
.
as_view
(
bound_actions
,
name_suffix
=
action_name
)
name
=
name_format
%
base_name
name
=
self
.
name_format
%
(
base_name
,
action_name
)
ret
.
append
(
url
(
regex
,
view
,
name
=
name
))
ret
.
append
(
url
(
regex
,
view
,
name
=
name
))
# Bind any extra `@action` or `@link` routes
# Bind any extra `@action` or `@link` routes
for
a
ttr
in
dir
(
viewset
):
for
a
ction_name
in
dir
(
viewset
):
func
=
getattr
(
viewset
,
a
ttr
)
func
=
getattr
(
viewset
,
a
ction_name
)
http_method
=
getattr
(
func
,
'bind_to_method'
,
None
)
http_method
=
getattr
(
func
,
'bind_to_method'
,
None
)
# Skip if this is not an @action or @link method
# Skip if this is not an @action or @link method
if
not
http_method
:
if
not
http_method
:
continue
continue
regex_format
,
name_format
=
self
.
extra_routes
suffix
=
self
.
extra_routes
%
action_name
# Build the url pattern
# Build the url pattern
regex
=
regex_format
%
attr
regex
=
prefix
+
suffix
view
=
viewset
.
as_view
({
http_method
:
a
ttr
},
**
func
.
kwargs
)
view
=
viewset
.
as_view
({
http_method
:
a
ction_name
},
**
func
.
kwargs
)
name
=
name_format
%
(
base_name
,
attr
)
name
=
self
.
name_format
%
(
base_name
,
action_name
)
ret
.
append
(
url
(
regex
,
view
,
name
=
name
))
ret
.
append
(
url
(
regex
,
view
,
name
=
name
))
# Return a list of url patterns
# Return a list of url patterns
...
...
rest_framework/utils/breadcrumbs.py
View file @
f68721ad
from
__future__
import
unicode_literals
from
__future__
import
unicode_literals
from
django.core.urlresolvers
import
resolve
,
get_script_prefix
from
django.core.urlresolvers
import
resolve
,
get_script_prefix
from
rest_framework.utils.formatting
import
get_view_name
def
get_breadcrumbs
(
url
):
def
get_breadcrumbs
(
url
):
...
@@ -16,11 +17,11 @@ def get_breadcrumbs(url):
...
@@ -16,11 +17,11 @@ def get_breadcrumbs(url):
pass
pass
else
:
else
:
# Check if this is a REST framework view, and if so add it to the breadcrumbs
# Check if this is a REST framework view, and if so add it to the breadcrumbs
if
is
instance
(
getattr
(
view
,
'cls_instance
'
,
None
),
APIView
):
if
is
subclass
(
getattr
(
view
,
'cls
'
,
None
),
APIView
):
# Don't list the same view twice in a row.
# Don't list the same view twice in a row.
# Probably an optional trailing slash.
# Probably an optional trailing slash.
if
not
seen
or
seen
[
-
1
]
!=
view
:
if
not
seen
or
seen
[
-
1
]
!=
view
:
breadcrumbs_list
.
insert
(
0
,
(
view
.
cls_instance
.
get_name
(
),
prefix
+
url
))
breadcrumbs_list
.
insert
(
0
,
(
get_view_name
(
view
.
cls
),
prefix
+
url
))
seen
.
append
(
view
)
seen
.
append
(
view
)
if
url
==
''
:
if
url
==
''
:
...
...
rest_framework/utils/formatting.py
0 → 100644
View file @
f68721ad
"""
Utility functions to return a formatted name and description for a given view.
"""
from
__future__
import
unicode_literals
from
django.utils.html
import
escape
from
django.utils.safestring
import
mark_safe
from
rest_framework.compat
import
apply_markdown
import
re
def
_remove_trailing_string
(
content
,
trailing
):
"""
Strip trailing component `trailing` from `content` if it exists.
Used when generating names from view classes.
"""
if
content
.
endswith
(
trailing
)
and
content
!=
trailing
:
return
content
[:
-
len
(
trailing
)]
return
content
def
_remove_leading_indent
(
content
):
"""
Remove leading indent from a block of text.
Used when generating descriptions from docstrings.
"""
whitespace_counts
=
[
len
(
line
)
-
len
(
line
.
lstrip
(
' '
))
for
line
in
content
.
splitlines
()[
1
:]
if
line
.
lstrip
()]
# unindent the content if needed
if
whitespace_counts
:
whitespace_pattern
=
'^'
+
(
' '
*
min
(
whitespace_counts
))
content
=
re
.
sub
(
re
.
compile
(
whitespace_pattern
,
re
.
MULTILINE
),
''
,
content
)
content
=
content
.
strip
(
'
\n
'
)
return
content
def
_camelcase_to_spaces
(
content
):
"""
Translate 'CamelCaseNames' to 'Camel Case Names'.
Used when generating names from view classes.
"""
camelcase_boundry
=
'(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))'
content
=
re
.
sub
(
camelcase_boundry
,
'
\\
1'
,
content
)
.
strip
()
return
' '
.
join
(
content
.
split
(
'_'
))
.
title
()
def
get_view_name
(
cls
):
"""
Return a formatted name for an `APIView` class or `@api_view` function.
"""
name
=
cls
.
__name__
name
=
_remove_trailing_string
(
name
,
'View'
)
name
=
_remove_trailing_string
(
name
,
'ViewSet'
)
return
_camelcase_to_spaces
(
name
)
def
get_view_description
(
cls
,
html
=
False
):
"""
Return a description for an `APIView` class or `@api_view` function.
"""
description
=
cls
.
__doc__
or
''
description
=
_remove_leading_indent
(
description
)
if
html
:
return
markup_description
(
description
)
return
description
def
markup_description
(
description
):
"""
Apply HTML markup to the given description.
"""
if
apply_markdown
:
description
=
apply_markdown
(
description
)
else
:
description
=
escape
(
description
)
.
replace
(
'
\n
'
,
'<br />'
)
return
mark_safe
(
description
)
rest_framework/views.py
View file @
f68721ad
...
@@ -4,51 +4,13 @@ Provides an APIView class that is used as the base of all class-based views.
...
@@ -4,51 +4,13 @@ Provides an APIView class that is used as the base of all class-based views.
from
__future__
import
unicode_literals
from
__future__
import
unicode_literals
from
django.core.exceptions
import
PermissionDenied
from
django.core.exceptions
import
PermissionDenied
from
django.http
import
Http404
from
django.http
import
Http404
from
django.utils.html
import
escape
from
django.utils.safestring
import
mark_safe
from
django.views.decorators.csrf
import
csrf_exempt
from
django.views.decorators.csrf
import
csrf_exempt
from
rest_framework
import
status
,
exceptions
from
rest_framework
import
status
,
exceptions
from
rest_framework.compat
import
View
,
apply_markdown
from
rest_framework.compat
import
View
from
rest_framework.response
import
Response
from
rest_framework.response
import
Response
from
rest_framework.request
import
Request
from
rest_framework.request
import
Request
from
rest_framework.settings
import
api_settings
from
rest_framework.settings
import
api_settings
import
re
from
rest_framework.utils.formatting
import
get_view_name
,
get_view_description
def
_remove_trailing_string
(
content
,
trailing
):
"""
Strip trailing component `trailing` from `content` if it exists.
Used when generating names from view classes.
"""
if
content
.
endswith
(
trailing
)
and
content
!=
trailing
:
return
content
[:
-
len
(
trailing
)]
return
content
def
_remove_leading_indent
(
content
):
"""
Remove leading indent from a block of text.
Used when generating descriptions from docstrings.
"""
whitespace_counts
=
[
len
(
line
)
-
len
(
line
.
lstrip
(
' '
))
for
line
in
content
.
splitlines
()[
1
:]
if
line
.
lstrip
()]
# unindent the content if needed
if
whitespace_counts
:
whitespace_pattern
=
'^'
+
(
' '
*
min
(
whitespace_counts
))
content
=
re
.
sub
(
re
.
compile
(
whitespace_pattern
,
re
.
MULTILINE
),
''
,
content
)
content
=
content
.
strip
(
'
\n
'
)
return
content
def
_camelcase_to_spaces
(
content
):
"""
Translate 'CamelCaseNames' to 'Camel Case Names'.
Used when generating names from view classes.
"""
camelcase_boundry
=
'(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))'
content
=
re
.
sub
(
camelcase_boundry
,
'
\\
1'
,
content
)
.
strip
()
return
' '
.
join
(
content
.
split
(
'_'
))
.
title
()
class
APIView
(
View
):
class
APIView
(
View
):
...
@@ -64,13 +26,13 @@ class APIView(View):
...
@@ -64,13 +26,13 @@ class APIView(View):
@classmethod
@classmethod
def
as_view
(
cls
,
**
initkwargs
):
def
as_view
(
cls
,
**
initkwargs
):
"""
"""
Override the default :meth:`as_view` to store an instance of the view
Store the original class on the view function.
as an attribute on the callable function. This allows us to discover
information about the view when we do URL reverse lookups.
This allows us to discover information about the view when we do URL
reverse lookups. Used for breadcrumb generation.
"""
"""
# TODO: deprecate?
view
=
super
(
APIView
,
cls
)
.
as_view
(
**
initkwargs
)
view
=
super
(
APIView
,
cls
)
.
as_view
(
**
initkwargs
)
view
.
cls
_instance
=
cls
(
**
initkwargs
)
view
.
cls
=
cls
return
view
return
view
@property
@property
...
@@ -90,43 +52,10 @@ class APIView(View):
...
@@ -90,43 +52,10 @@ class APIView(View):
'Vary'
:
'Accept'
'Vary'
:
'Accept'
}
}
def
get_name
(
self
):
"""
Return the resource or view class name for use as this view's name.
Override to customize.
"""
# TODO: deprecate?
name
=
self
.
__class__
.
__name__
name
=
_remove_trailing_string
(
name
,
'View'
)
return
_camelcase_to_spaces
(
name
)
def
get_description
(
self
,
html
=
False
):
"""
Return the resource or view docstring for use as this view's description.
Override to customize.
"""
# TODO: deprecate?
description
=
self
.
__doc__
or
''
description
=
_remove_leading_indent
(
description
)
if
html
:
return
self
.
markup_description
(
description
)
return
description
def
markup_description
(
self
,
description
):
"""
Apply HTML markup to the description of this view.
"""
# TODO: deprecate?
if
apply_markdown
:
description
=
apply_markdown
(
description
)
else
:
description
=
escape
(
description
)
.
replace
(
'
\n
'
,
'<br />'
)
return
mark_safe
(
description
)
def
metadata
(
self
,
request
):
def
metadata
(
self
,
request
):
return
{
return
{
'name'
:
self
.
get_name
(
),
'name'
:
get_view_name
(
self
.
__class__
),
'description'
:
self
.
get_description
(
),
'description'
:
get_view_description
(
self
.
__class__
),
'renders'
:
[
renderer
.
media_type
for
renderer
in
self
.
renderer_classes
],
'renders'
:
[
renderer
.
media_type
for
renderer
in
self
.
renderer_classes
],
'parses'
:
[
parser
.
media_type
for
parser
in
self
.
parser_classes
],
'parses'
:
[
parser
.
media_type
for
parser
in
self
.
parser_classes
],
}
}
...
...
rest_framework/viewsets.py
View file @
f68721ad
...
@@ -15,9 +15,10 @@ class ViewSetMixin(object):
...
@@ -15,9 +15,10 @@ class ViewSetMixin(object):
view = MyViewSet.as_view({'get': 'list', 'post': 'create'})
view = MyViewSet.as_view({'get': 'list', 'post': 'create'})
"""
"""
_is_viewset
=
True
@classonlymethod
@classonlymethod
def
as_view
(
cls
,
actions
=
None
,
**
initkwargs
):
def
as_view
(
cls
,
actions
=
None
,
name_suffix
=
None
,
**
initkwargs
):
"""
"""
Main entry point for a request-response process.
Main entry point for a request-response process.
...
@@ -57,6 +58,8 @@ class ViewSetMixin(object):
...
@@ -57,6 +58,8 @@ class ViewSetMixin(object):
# and possible attributes set by decorators
# and possible attributes set by decorators
# like csrf_exempt from dispatch
# like csrf_exempt from dispatch
update_wrapper
(
view
,
cls
.
dispatch
,
assigned
=
())
update_wrapper
(
view
,
cls
.
dispatch
,
assigned
=
())
view
.
cls
=
cls
return
view
return
view
...
...
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