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
c5317591
Commit
c5317591
authored
May 23, 2011
by
Tom Christie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
name and description
parent
e7f8c06d
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
125 additions
and
49 deletions
+125
-49
.hgignore
+1
-0
djangorestframework/mixins.py
+3
-2
djangorestframework/tests/description.py
+22
-20
djangorestframework/utils/description.py
+73
-20
djangorestframework/views.py
+17
-5
examples/blogpost/urls.py
+9
-2
No files found.
.hgignore
View file @
c5317591
...
...
@@ -2,6 +2,7 @@ syntax: glob
*.pyc
*.db
assetplatform.egg-info/*
*~
coverage.xml
env
...
...
djangorestframework/mixins.py
View file @
c5317591
...
...
@@ -467,12 +467,13 @@ class InstanceMixin(object):
Store the callable object on the resource class that has been associated with this view.
"""
view
=
super
(
InstanceMixin
,
cls
)
.
as_view
(
**
initkwargs
)
if
'resource'
in
initkwargs
:
resource
=
getattr
(
cls
(
**
initkwargs
),
'resource'
,
None
)
if
resource
:
# We do a little dance when we store the view callable...
# we need to store it wrapped in a 1-tuple, so that inspect will treat it
# as a function when we later look it up (rather than turning it into a method).
# This makes sure our URL reversing works ok.
initkwargs
[
'resource'
]
.
view_callable
=
(
view
,)
resource
.
view_callable
=
(
view
,)
return
view
...
...
djangorestframework/tests/description.py
View file @
c5317591
...
...
@@ -37,14 +37,15 @@ class TestViewNamesAndDescriptions(TestCase):
"""Ensure Resource names are based on the classname by default."""
class
MockView
(
BaseView
):
pass
self
.
assertEquals
(
get_name
(
MockView
()),
'Mock
View
'
)
self
.
assertEquals
(
get_name
(
MockView
()),
'Mock'
)
def
test_resource_name_can_be_set_explicitly
(
self
):
"""Ensure Resource names can be set using the 'name' class attribute."""
example
=
'Some Other Name'
class
MockView
(
BaseView
):
name
=
example
self
.
assertEquals
(
get_name
(
MockView
()),
example
)
# This has been turned off now.
#def test_resource_name_can_be_set_explicitly(self):
# """Ensure Resource names can be set using the 'name' class attribute."""
# example = 'Some Other Name'
# class MockView(BaseView):
# name = example
# self.assertEquals(get_name(MockView()), example)
def
test_resource_description_uses_docstring_by_default
(
self
):
"""Ensure Resource names are based on the docstring by default."""
...
...
@@ -66,20 +67,21 @@ class TestViewNamesAndDescriptions(TestCase):
self
.
assertEquals
(
get_description
(
MockView
()),
DESCRIPTION
)
def
test_resource_description_can_be_set_explicitly
(
self
):
"""Ensure Resource descriptions can be set using the 'description' class attribute."""
example
=
'Some other description'
class
MockView
(
BaseView
):
"""docstring"""
description
=
example
self
.
assertEquals
(
get_description
(
MockView
()),
example
)
# This has been turned off now
#def test_resource_description_can_be_set_explicitly(self):
# """Ensure Resource descriptions can be set using the 'description' class attribute."""
# example = 'Some other description'
# class MockView(BaseView):
# """docstring"""
# description = example
# self.assertEquals(get_description(MockView()), example)
def
test_resource_description_does_not_require_docstring
(
self
):
"""Ensure that empty docstrings do not affect the Resource's description if it has been set using the 'description' class attribute."""
example
=
'Some other description'
class
MockView
(
BaseView
):
description
=
example
self
.
assertEquals
(
get_description
(
MockView
()),
example
)
#
def test_resource_description_does_not_require_docstring(self):
#
"""Ensure that empty docstrings do not affect the Resource's description if it has been set using the 'description' class attribute."""
#
example = 'Some other description'
#
class MockView(BaseView):
#
description = example
#
self.assertEquals(get_description(MockView()), example)
def
test_resource_description_can_be_empty
(
self
):
"""Ensure that if a resource has no doctring or 'description' class attribute, then it's description is the empty string"""
...
...
djangorestframework/utils/description.py
View file @
c5317591
"""Get a descriptive name and description for a view,
based on class name and docstring, and override-able by 'name' and 'description' attributes"""
"""
Get a descriptive name and description for a view.
"""
import
re
from
djangorestframework.resources
import
Resource
,
FormResource
,
ModelResource
# These a a bit Grungy, but they do the job.
def
get_name
(
view
):
"""Return a name for the view.
"""
Return a name for the view.
If view has a name attribute, use that, otherwise use the view's class name, with 'CamelCaseNames' converted to 'Camel Case Names'."""
if
getattr
(
view
,
'name'
,
None
)
is
not
None
:
return
view
.
name
If view has a name attribute, use that, otherwise use the view's class name, with 'CamelCaseNames' converted to 'Camel Case Names'.
"""
# If we're looking up the name of a view callable, as found by reverse,
# grok the class instance that we stored when as_view was called.
if
getattr
(
view
,
'cls_instance'
,
None
):
view
=
view
.
cls_instance
if
getattr
(
view
,
'__name__'
,
None
)
is
not
None
:
# If this view has a resource that's been overridden, then use that resource for the name
if
getattr
(
view
,
'resource'
,
None
)
not
in
(
None
,
Resource
,
FormResource
,
ModelResource
):
name
=
view
.
resource
.
__name__
# Chomp of any non-descriptive trailing part of the resource class name
if
name
.
endswith
(
'Resource'
)
and
name
!=
'Resource'
:
name
=
name
[:
-
len
(
'Resource'
)]
# If the view has a descriptive suffix, eg '*** List', '*** Instance'
if
getattr
(
view
,
'_suffix'
,
None
):
name
+=
view
.
_suffix
# Otherwise if it's a function view use the function's name
elif
getattr
(
view
,
'__name__'
,
None
)
is
not
None
:
name
=
view
.
__name__
elif
getattr
(
view
,
'__class__'
,
None
)
is
not
None
:
# TODO: should be able to get rid of this case once refactoring to 1.3 class views is complete
# If it's a view class with no resource then grok the name from the class name
elif
getattr
(
view
,
'__class__'
,
None
)
is
not
None
:
name
=
view
.
__class__
.
__name__
# Chomp of any non-descriptive trailing part of the view class name
if
name
.
endswith
(
'View'
)
and
name
!=
'View'
:
name
=
name
[:
-
len
(
'View'
)]
# I ain't got nuthin fo' ya
else
:
return
''
return
re
.
sub
(
'(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))'
,
'
\\
1'
,
name
)
.
strip
()
def
get_description
(
view
):
"""Provide a description for the view.
"""
Provide a description for the view.
By default this is the view's docstring with nice unindention applied."""
if
getattr
(
view
,
'description'
,
None
)
is
not
None
:
return
getattr
(
view
,
'description'
)
By default this is the view's docstring with nice unindention applied.
"""
# If we're looking up the name of a view callable, as found by reverse,
# grok the class instance that we stored when as_view was called.
if
getattr
(
view
,
'cls_instance'
,
None
):
view
=
view
.
cls_instance
# If this view has a resource that's been overridden, then use the resource's doctring
if
getattr
(
view
,
'resource'
,
None
)
not
in
(
None
,
Resource
,
FormResource
,
ModelResource
):
doc
=
view
.
resource
.
__doc__
# Otherwise use the view doctring
elif
getattr
(
view
,
'__doc__'
,
None
):
doc
=
view
.
__doc__
# I ain't got nuthin fo' ya
else
:
return
''
if
not
doc
:
return
''
if
getattr
(
view
,
'__doc__'
,
None
)
is
not
None
:
whitespace_counts
=
[
len
(
line
)
-
len
(
line
.
lstrip
(
' '
))
for
line
in
view
.
__doc__
.
splitlines
()[
1
:]
if
line
.
lstrip
()]
whitespace_counts
=
[
len
(
line
)
-
len
(
line
.
lstrip
(
' '
))
for
line
in
doc
.
splitlines
()[
1
:]
if
line
.
lstrip
()]
if
whitespace_counts
:
whitespace_pattern
=
'^'
+
(
' '
*
min
(
whitespace_counts
))
return
re
.
sub
(
re
.
compile
(
whitespace_pattern
,
re
.
MULTILINE
),
''
,
view
.
__doc__
)
# unindent the docstring if needed
if
whitespace_counts
:
whitespace_pattern
=
'^'
+
(
' '
*
min
(
whitespace_counts
))
return
re
.
sub
(
re
.
compile
(
whitespace_pattern
,
re
.
MULTILINE
),
''
,
doc
)
return
view
.
__doc__
# otherwise return it as-is
return
doc
return
''
\ No newline at end of file
djangorestframework/views.py
View file @
c5317591
...
...
@@ -51,6 +51,18 @@ class BaseView(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, View):
name
=
None
description
=
None
@classmethod
def
as_view
(
cls
,
**
initkwargs
):
"""
Override the default :meth:`as_view` to store an instance of the view
as an attribute on the callable function. This allows us to discover
information about the view when we do URL reverse lookups.
"""
view
=
super
(
BaseView
,
cls
)
.
as_view
(
**
initkwargs
)
view
.
cls_instance
=
cls
(
**
initkwargs
)
return
view
@property
def
allowed_methods
(
self
):
"""
...
...
@@ -122,12 +134,12 @@ class ModelView(BaseView):
class
InstanceModelView
(
InstanceMixin
,
ReadModelMixin
,
UpdateModelMixin
,
DeleteModelMixin
,
ModelView
):
"""A view which provides default operations for read/update/delete against a model instance."""
pass
_suffix
=
'Instance'
class
ListModelView
(
ListModelMixin
,
ModelView
):
"""A view which provides default operations for list, against a model in the database."""
pass
"""A view which provides default operations for list, against a model in the database."""
_suffix
=
'List'
class
ListOrCreateModelView
(
ListModelMixin
,
CreateModelMixin
,
ModelView
):
"""A view which provides default operations for list and create, against a model in the database."""
pass
"""A view which provides default operations for list and create, against a model in the database."""
_suffix
=
'List'
examples/blogpost/urls.py
View file @
c5317591
...
...
@@ -6,7 +6,11 @@ from djangorestframework.resources import ModelResource
from
blogpost.models
import
BlogPost
,
Comment
class
BlogPostResource
(
ModelResource
):
"""
A Blog Post has a *title* and *content*, and can be associated with zero or more comments.
"""
model
=
BlogPost
fields
=
(
'created'
,
'title'
,
'slug'
,
'content'
,
'url'
,
'comments'
)
ordering
=
(
'-created'
,)
...
...
@@ -14,7 +18,11 @@ class BlogPostResource(ModelResource):
def
comments
(
self
,
instance
):
return
reverse
(
'comments'
,
kwargs
=
{
'blogpost'
:
instance
.
key
})
class
CommentResource
(
ModelResource
):
"""
A Comment is associated with a given Blog Post and has a *username* and *comment*, and optionally a *rating*.
"""
model
=
Comment
fields
=
(
'username'
,
'comment'
,
'created'
,
'rating'
,
'url'
,
'blogpost'
)
ordering
=
(
'-created'
,)
...
...
@@ -25,4 +33,4 @@ urlpatterns = patterns('',
url
(
r'^(?P<key>[^/]+)/$'
,
InstanceModelView
.
as_view
(
resource
=
BlogPostResource
)),
url
(
r'^(?P<blogpost>[^/]+)/comments/$'
,
ListOrCreateModelView
.
as_view
(
resource
=
CommentResource
),
name
=
'comments'
),
url
(
r'^(?P<blogpost>[^/]+)/comments/(?P<id>[^/]+)/$'
,
InstanceModelView
.
as_view
(
resource
=
CommentResource
)),
)
\ No newline at end of file
)
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