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
42b3fdbd
Commit
42b3fdbd
authored
Oct 04, 2012
by
Tom Christie
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #279 from tomchristie/hyperlinked-relationships
Hyperlinked relationships
parents
ad214976
eaebb397
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
115 additions
and
17 deletions
+115
-17
rest_framework/fields.py
+0
-0
rest_framework/serializers.py
+54
-15
rest_framework/settings.py
+1
-1
rest_framework/tests/generics.py
+0
-1
rest_framework/tests/hyperlinkedserializers.py
+60
-0
No files found.
rest_framework/fields.py
View file @
42b3fdbd
This diff is collapsed.
Click to expand it.
rest_framework/serializers.py
View file @
42b3fdbd
...
...
@@ -123,16 +123,8 @@ class BaseSerializer(Field):
# Get the explicitly declared fields
for
key
,
field
in
self
.
fields
.
items
():
ret
[
key
]
=
field
# Determine if the declared field corrosponds to a model field.
try
:
if
key
==
'pk'
:
model_field
=
obj
.
_meta
.
pk
else
:
model_field
=
obj
.
_meta
.
get_field_by_name
(
key
)[
0
]
except
:
model_field
=
None
# Set up the field
field
.
initialize
(
parent
=
self
,
model_field
=
model_field
)
field
.
initialize
(
parent
=
self
)
# Add in the default fields
fields
=
self
.
default_fields
(
serialize
,
obj
,
data
,
nested
)
...
...
@@ -157,12 +149,12 @@ class BaseSerializer(Field):
#####
# Field methods - used when the serializer class is itself used as a field.
def
initialize
(
self
,
parent
,
model_field
=
None
):
def
initialize
(
self
,
parent
):
"""
Same behaviour as usual Field, except that we need to keep track
of state so that we can deal with handling maximum depth and recursion.
"""
super
(
BaseSerializer
,
self
)
.
initialize
(
parent
,
model_field
)
super
(
BaseSerializer
,
self
)
.
initialize
(
parent
)
self
.
stack
=
parent
.
stack
[:]
if
parent
.
opts
.
nested
and
not
isinstance
(
parent
.
opts
.
nested
,
bool
):
self
.
opts
.
nested
=
parent
.
opts
.
nested
-
1
...
...
@@ -296,12 +288,22 @@ class ModelSerializerOptions(SerializerOptions):
self
.
model
=
getattr
(
meta
,
'model'
,
None
)
class
ModelSerializer
(
RelatedField
,
Serializer
):
class
ModelSerializer
(
Serializer
):
"""
A serializer that deals with model instances and querysets.
"""
_options_class
=
ModelSerializerOptions
def
field_to_native
(
self
,
obj
,
field_name
):
"""
Override default so that we can apply ModelSerializer as a nested
field to relationships.
"""
obj
=
getattr
(
obj
,
self
.
source
or
field_name
)
if
obj
.
__class__
.
__name__
in
(
'RelatedManager'
,
'ManyRelatedManager'
):
return
[
self
.
to_native
(
item
)
for
item
in
obj
.
all
()]
return
self
.
to_native
(
obj
)
def
default_fields
(
self
,
serialize
,
obj
=
None
,
data
=
None
,
nested
=
False
):
"""
Return all the fields that should be serialized for the model.
...
...
@@ -330,7 +332,7 @@ class ModelSerializer(RelatedField, Serializer):
field
=
self
.
get_field
(
model_field
)
if
field
:
field
.
initialize
(
parent
=
self
,
model_field
=
model_field
)
field
.
initialize
(
parent
=
self
)
ret
[
model_field
.
name
]
=
field
return
ret
...
...
@@ -339,7 +341,7 @@ class ModelSerializer(RelatedField, Serializer):
"""
Returns a default instance of the pk field.
"""
return
Field
(
readonly
=
True
)
return
Field
()
def
get_nested_field
(
self
,
model_field
):
"""
...
...
@@ -373,7 +375,7 @@ class ModelSerializer(RelatedField, Serializer):
try
:
return
field_mapping
[
model_field
.
__class__
]()
except
KeyError
:
return
Field
(
)
return
ModelField
(
model_field
=
model_field
)
def
restore_object
(
self
,
attrs
,
instance
=
None
):
"""
...
...
@@ -396,3 +398,40 @@ class ModelSerializer(RelatedField, Serializer):
"""
self
.
object
.
save
()
return
self
.
object
.
object
class
HyperlinkedModelSerializerOptions
(
ModelSerializerOptions
):
"""
Options for HyperlinkedModelSerializer
"""
def
__init__
(
self
,
meta
):
super
(
HyperlinkedModelSerializerOptions
,
self
)
.
__init__
(
meta
)
self
.
view_name
=
getattr
(
meta
,
'view_name'
,
None
)
class
HyperlinkedModelSerializer
(
ModelSerializer
):
"""
"""
_options_class
=
HyperlinkedModelSerializerOptions
_default_view_name
=
'
%(model_name)
s-detail'
url
=
HyperlinkedIdentityField
()
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
(
HyperlinkedModelSerializer
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
if
self
.
opts
.
view_name
is
None
:
self
.
opts
.
view_name
=
self
.
_get_default_view_name
()
def
_get_default_view_name
(
self
):
"""
Return the view name to use if 'view_name' is not specified in 'Meta'
"""
model_meta
=
self
.
opts
.
model
.
_meta
format_kwargs
=
{
'app_label'
:
model_meta
.
app_label
,
'model_name'
:
model_meta
.
object_name
.
lower
()
}
return
self
.
_default_view_name
%
format_kwargs
def
get_pk_field
(
self
,
model_field
):
return
None
rest_framework/settings.py
View file @
42b3fdbd
...
...
@@ -46,7 +46,7 @@ DEFAULTS = {
'MODEL_SERIALIZER'
:
'rest_framework.serializers.ModelSerializer'
,
'PAGINATION_SERIALIZER'
:
'rest_framework.pagination.PaginationSerializer'
,
'PAGINATE_BY'
:
20
,
'PAGINATE_BY'
:
None
,
'UNAUTHENTICATED_USER'
:
'django.contrib.auth.models.AnonymousUser'
,
'UNAUTHENTICATED_TOKEN'
:
None
,
...
...
rest_framework/tests/generics.py
View file @
42b3fdbd
...
...
@@ -13,7 +13,6 @@ class RootView(generics.ListCreateAPIView):
Example description for OPTIONS.
"""
model
=
BasicModel
paginate_by
=
None
class
InstanceView
(
generics
.
RetrieveUpdateDestroyAPIView
):
...
...
rest_framework/tests/hyperlinkedserializers.py
0 → 100644
View file @
42b3fdbd
from
django.conf.urls.defaults
import
patterns
,
url
from
django.test
import
TestCase
from
django.test.client
import
RequestFactory
from
rest_framework
import
generics
,
status
,
serializers
from
rest_framework.tests.models
import
BasicModel
factory
=
RequestFactory
()
class
BasicList
(
generics
.
ListCreateAPIView
):
model
=
BasicModel
model_serializer_class
=
serializers
.
HyperlinkedModelSerializer
class
BasicDetail
(
generics
.
RetrieveUpdateDestroyAPIView
):
model
=
BasicModel
model_serializer_class
=
serializers
.
HyperlinkedModelSerializer
urlpatterns
=
patterns
(
''
,
url
(
r'^basic/$'
,
BasicList
.
as_view
(),
name
=
'basicmodel-list'
),
url
(
r'^basic/(?P<pk>\d+)/$'
,
BasicDetail
.
as_view
(),
name
=
'basicmodel-detail'
),
)
class
TestHyperlinkedView
(
TestCase
):
urls
=
'rest_framework.tests.hyperlinkedserializers'
def
setUp
(
self
):
"""
Create 3 BasicModel intances.
"""
items
=
[
'foo'
,
'bar'
,
'baz'
]
for
item
in
items
:
BasicModel
(
text
=
item
)
.
save
()
self
.
objects
=
BasicModel
.
objects
self
.
data
=
[
{
'url'
:
'http://testserver/basic/
%
d/'
%
obj
.
id
,
'text'
:
obj
.
text
}
for
obj
in
self
.
objects
.
all
()
]
self
.
list_view
=
BasicList
.
as_view
()
self
.
detail_view
=
BasicDetail
.
as_view
()
def
test_get_list_view
(
self
):
"""
GET requests to ListCreateAPIView should return list of objects.
"""
request
=
factory
.
get
(
'/'
)
response
=
self
.
list_view
(
request
)
.
render
()
self
.
assertEquals
(
response
.
status_code
,
status
.
HTTP_200_OK
)
self
.
assertEquals
(
response
.
data
,
self
.
data
)
def
test_get_detail_view
(
self
):
"""
GET requests to ListCreateAPIView should return list of objects.
"""
request
=
factory
.
get
(
'/1'
)
response
=
self
.
detail_view
(
request
,
pk
=
1
)
.
render
()
self
.
assertEquals
(
response
.
status_code
,
status
.
HTTP_200_OK
)
self
.
assertEquals
(
response
.
data
,
self
.
data
[
0
])
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