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
9fe6a103
Commit
9fe6a103
authored
May 18, 2013
by
Tom Christie
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #694 from craigds/master
fix function names and dotted lookups for use in PrimaryKeyRelatedField
parents
a73c16b8
c992b600
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
192 additions
and
22 deletions
+192
-22
rest_framework/relations.py
+11
-3
rest_framework/tests/relations.py
+54
-1
rest_framework/tests/relations_hyperlink.py
+71
-0
rest_framework/tests/relations_pk.py
+56
-1
rest_framework/tests/serializer.py
+0
-17
No files found.
rest_framework/relations.py
View file @
9fe6a103
...
...
@@ -221,12 +221,20 @@ class PrimaryKeyRelatedField(RelatedField):
def
field_to_native
(
self
,
obj
,
field_name
):
if
self
.
many
:
# To-many relationship
try
:
queryset
=
None
if
not
self
.
source
:
# Prefer obj.serializable_value for performance reasons
queryset
=
obj
.
serializable_value
(
self
.
source
or
field_name
)
try
:
queryset
=
obj
.
serializable_value
(
field_name
)
except
AttributeError
:
pass
if
queryset
is
None
:
# RelatedManager (reverse relationship)
queryset
=
getattr
(
obj
,
self
.
source
or
field_name
)
source
=
self
.
source
or
field_name
queryset
=
obj
for
component
in
source
.
split
(
'.'
):
queryset
=
get_component
(
queryset
,
component
)
# Forward relationship
return
[
self
.
to_native
(
item
.
pk
)
for
item
in
queryset
.
all
()]
...
...
rest_framework/tests/relations.py
View file @
9fe6a103
...
...
@@ -5,6 +5,7 @@ from __future__ import unicode_literals
from
django.db
import
models
from
django.test
import
TestCase
from
rest_framework
import
serializers
from
rest_framework.tests.models
import
BlogPost
class
NullModel
(
models
.
Model
):
...
...
@@ -33,7 +34,7 @@ class FieldTests(TestCase):
self
.
assertRaises
(
serializers
.
ValidationError
,
field
.
from_native
,
[])
class
TestManyRelateMixin
(
TestCase
):
class
TestManyRelate
d
Mixin
(
TestCase
):
def
test_missing_many_to_many_related_field
(
self
):
'''
Regression test for #632
...
...
@@ -45,3 +46,55 @@ class TestManyRelateMixin(TestCase):
into
=
{}
field
.
field_from_native
({},
None
,
'field_name'
,
into
)
self
.
assertEqual
(
into
[
'field_name'
],
[])
# Regression tests for #694 (`source` attribute on related fields)
class
RelatedFieldSourceTests
(
TestCase
):
def
test_related_manager_source
(
self
):
"""
Relational fields should be able to use manager-returning methods as their source.
"""
BlogPost
.
objects
.
create
(
title
=
'blah'
)
field
=
serializers
.
RelatedField
(
many
=
True
,
source
=
'get_blogposts_manager'
)
class
ClassWithManagerMethod
(
object
):
def
get_blogposts_manager
(
self
):
return
BlogPost
.
objects
obj
=
ClassWithManagerMethod
()
value
=
field
.
field_to_native
(
obj
,
'field_name'
)
self
.
assertEqual
(
value
,
[
'BlogPost object'
])
def
test_related_queryset_source
(
self
):
"""
Relational fields should be able to use queryset-returning methods as their source.
"""
BlogPost
.
objects
.
create
(
title
=
'blah'
)
field
=
serializers
.
RelatedField
(
many
=
True
,
source
=
'get_blogposts_queryset'
)
class
ClassWithQuerysetMethod
(
object
):
def
get_blogposts_queryset
(
self
):
return
BlogPost
.
objects
.
all
()
obj
=
ClassWithQuerysetMethod
()
value
=
field
.
field_to_native
(
obj
,
'field_name'
)
self
.
assertEqual
(
value
,
[
'BlogPost object'
])
def
test_dotted_source
(
self
):
"""
Source argument should support dotted.source notation.
"""
BlogPost
.
objects
.
create
(
title
=
'blah'
)
field
=
serializers
.
RelatedField
(
many
=
True
,
source
=
'a.b.c'
)
class
ClassWithQuerysetMethod
(
object
):
a
=
{
'b'
:
{
'c'
:
BlogPost
.
objects
.
all
()
}
}
obj
=
ClassWithQuerysetMethod
()
value
=
field
.
field_to_native
(
obj
,
'field_name'
)
self
.
assertEqual
(
value
,
[
'BlogPost object'
])
rest_framework/tests/relations_hyperlink.py
View file @
9fe6a103
...
...
@@ -4,6 +4,7 @@ from django.test.client import RequestFactory
from
rest_framework
import
serializers
from
rest_framework.compat
import
patterns
,
url
from
rest_framework.tests.models
import
(
BlogPost
,
ManyToManyTarget
,
ManyToManySource
,
ForeignKeyTarget
,
ForeignKeySource
,
NullableForeignKeySource
,
OneToOneTarget
,
NullableOneToOneSource
)
...
...
@@ -16,6 +17,7 @@ def dummy_view(request, pk):
pass
urlpatterns
=
patterns
(
''
,
url
(
r'^dummyurl/(?P<pk>[0-9]+)/$'
,
dummy_view
,
name
=
'dummy-url'
),
url
(
r'^manytomanysource/(?P<pk>[0-9]+)/$'
,
dummy_view
,
name
=
'manytomanysource-detail'
),
url
(
r'^manytomanytarget/(?P<pk>[0-9]+)/$'
,
dummy_view
,
name
=
'manytomanytarget-detail'
),
url
(
r'^foreignkeysource/(?P<pk>[0-9]+)/$'
,
dummy_view
,
name
=
'foreignkeysource-detail'
),
...
...
@@ -451,3 +453,72 @@ class HyperlinkedNullableOneToOneTests(TestCase):
{
'url'
:
'http://testserver/onetoonetarget/2/'
,
'name'
:
'target-2'
,
'nullable_source'
:
None
},
]
self
.
assertEqual
(
serializer
.
data
,
expected
)
# Regression tests for #694 (`source` attribute on related fields)
class
HyperlinkedRelatedFieldSourceTests
(
TestCase
):
urls
=
'rest_framework.tests.relations_hyperlink'
def
test_related_manager_source
(
self
):
"""
Relational fields should be able to use manager-returning methods as their source.
"""
BlogPost
.
objects
.
create
(
title
=
'blah'
)
field
=
serializers
.
HyperlinkedRelatedField
(
many
=
True
,
source
=
'get_blogposts_manager'
,
view_name
=
'dummy-url'
,
)
field
.
context
=
{
'request'
:
request
}
class
ClassWithManagerMethod
(
object
):
def
get_blogposts_manager
(
self
):
return
BlogPost
.
objects
obj
=
ClassWithManagerMethod
()
value
=
field
.
field_to_native
(
obj
,
'field_name'
)
self
.
assertEqual
(
value
,
[
'http://testserver/dummyurl/1/'
])
def
test_related_queryset_source
(
self
):
"""
Relational fields should be able to use queryset-returning methods as their source.
"""
BlogPost
.
objects
.
create
(
title
=
'blah'
)
field
=
serializers
.
HyperlinkedRelatedField
(
many
=
True
,
source
=
'get_blogposts_queryset'
,
view_name
=
'dummy-url'
,
)
field
.
context
=
{
'request'
:
request
}
class
ClassWithQuerysetMethod
(
object
):
def
get_blogposts_queryset
(
self
):
return
BlogPost
.
objects
.
all
()
obj
=
ClassWithQuerysetMethod
()
value
=
field
.
field_to_native
(
obj
,
'field_name'
)
self
.
assertEqual
(
value
,
[
'http://testserver/dummyurl/1/'
])
def
test_dotted_source
(
self
):
"""
Source argument should support dotted.source notation.
"""
BlogPost
.
objects
.
create
(
title
=
'blah'
)
field
=
serializers
.
HyperlinkedRelatedField
(
many
=
True
,
source
=
'a.b.c'
,
view_name
=
'dummy-url'
,
)
field
.
context
=
{
'request'
:
request
}
class
ClassWithQuerysetMethod
(
object
):
a
=
{
'b'
:
{
'c'
:
BlogPost
.
objects
.
all
()
}
}
obj
=
ClassWithQuerysetMethod
()
value
=
field
.
field_to_native
(
obj
,
'field_name'
)
self
.
assertEqual
(
value
,
[
'http://testserver/dummyurl/1/'
])
rest_framework/tests/relations_pk.py
View file @
9fe6a103
from
__future__
import
unicode_literals
from
django.test
import
TestCase
from
rest_framework
import
serializers
from
rest_framework.tests.models
import
ManyToManyTarget
,
ManyToManySource
,
ForeignKeyTarget
,
ForeignKeySource
,
NullableForeignKeySource
,
OneToOneTarget
,
NullableOneToOneSource
from
rest_framework.tests.models
import
(
BlogPost
,
ManyToManyTarget
,
ManyToManySource
,
ForeignKeyTarget
,
ForeignKeySource
,
NullableForeignKeySource
,
OneToOneTarget
,
NullableOneToOneSource
,
)
from
rest_framework.compat
import
six
...
...
@@ -421,3 +424,55 @@ class PKNullableOneToOneTests(TestCase):
{
'id'
:
2
,
'name'
:
'target-2'
,
'nullable_source'
:
1
},
]
self
.
assertEqual
(
serializer
.
data
,
expected
)
# Regression tests for #694 (`source` attribute on related fields)
class
PrimaryKeyRelatedFieldSourceTests
(
TestCase
):
def
test_related_manager_source
(
self
):
"""
Relational fields should be able to use manager-returning methods as their source.
"""
BlogPost
.
objects
.
create
(
title
=
'blah'
)
field
=
serializers
.
PrimaryKeyRelatedField
(
many
=
True
,
source
=
'get_blogposts_manager'
)
class
ClassWithManagerMethod
(
object
):
def
get_blogposts_manager
(
self
):
return
BlogPost
.
objects
obj
=
ClassWithManagerMethod
()
value
=
field
.
field_to_native
(
obj
,
'field_name'
)
self
.
assertEqual
(
value
,
[
1
])
def
test_related_queryset_source
(
self
):
"""
Relational fields should be able to use queryset-returning methods as their source.
"""
BlogPost
.
objects
.
create
(
title
=
'blah'
)
field
=
serializers
.
PrimaryKeyRelatedField
(
many
=
True
,
source
=
'get_blogposts_queryset'
)
class
ClassWithQuerysetMethod
(
object
):
def
get_blogposts_queryset
(
self
):
return
BlogPost
.
objects
.
all
()
obj
=
ClassWithQuerysetMethod
()
value
=
field
.
field_to_native
(
obj
,
'field_name'
)
self
.
assertEqual
(
value
,
[
1
])
def
test_dotted_source
(
self
):
"""
Source argument should support dotted.source notation.
"""
BlogPost
.
objects
.
create
(
title
=
'blah'
)
field
=
serializers
.
PrimaryKeyRelatedField
(
many
=
True
,
source
=
'a.b.c'
)
class
ClassWithQuerysetMethod
(
object
):
a
=
{
'b'
:
{
'c'
:
BlogPost
.
objects
.
all
()
}
}
obj
=
ClassWithQuerysetMethod
()
value
=
field
.
field_to_native
(
obj
,
'field_name'
)
self
.
assertEqual
(
value
,
[
1
])
rest_framework/tests/serializer.py
View file @
9fe6a103
...
...
@@ -871,23 +871,6 @@ class RelatedTraversalTest(TestCase):
self
.
assertEqual
(
serializer
.
data
,
expected
)
def
test_queryset_nested_traversal
(
self
):
"""
Relational fields should be able to use methods as their source.
"""
BlogPost
.
objects
.
create
(
title
=
'blah'
)
class
QuerysetMethodSerializer
(
serializers
.
Serializer
):
blogposts
=
serializers
.
RelatedField
(
many
=
True
,
source
=
'get_all_blogposts'
)
class
ClassWithQuerysetMethod
(
object
):
def
get_all_blogposts
(
self
):
return
BlogPost
.
objects
obj
=
ClassWithQuerysetMethod
()
serializer
=
QuerysetMethodSerializer
(
obj
)
self
.
assertEqual
(
serializer
.
data
,
{
'blogposts'
:
[
'BlogPost object'
]})
class
SerializerMethodFieldTests
(
TestCase
):
def
setUp
(
self
):
...
...
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