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
3f79a9a3
Commit
3f79a9a3
authored
Mar 22, 2013
by
Tom Christie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
one-one writable nested modelserializers
parent
9fdb661c
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
92 additions
and
73 deletions
+92
-73
rest_framework/serializers.py
+10
-1
rest_framework/tests/relations_nested.py
+82
-72
No files found.
rest_framework/serializers.py
View file @
3f79a9a3
...
@@ -753,7 +753,16 @@ class ModelSerializer(Serializer):
...
@@ -753,7 +753,16 @@ class ModelSerializer(Serializer):
if
getattr
(
obj
,
'_related_data'
,
None
):
if
getattr
(
obj
,
'_related_data'
,
None
):
for
accessor_name
,
related
in
obj
.
_related_data
.
items
():
for
accessor_name
,
related
in
obj
.
_related_data
.
items
():
setattr
(
obj
,
accessor_name
,
related
)
if
related
is
None
:
previous
=
getattr
(
obj
,
accessor_name
,
related
)
if
previous
:
previous
.
delete
()
elif
isinstance
(
related
,
models
.
Model
):
fk_field
=
obj
.
_meta
.
get_field_by_name
(
accessor_name
)[
0
]
.
field
.
name
setattr
(
related
,
fk_field
,
obj
)
self
.
save_object
(
related
)
else
:
setattr
(
obj
,
accessor_name
,
related
)
del
(
obj
.
_related_data
)
del
(
obj
.
_related_data
)
...
...
rest_framework/tests/relations_nested.py
View file @
3f79a9a3
from
__future__
import
unicode_literals
from
__future__
import
unicode_literals
from
django.db
import
models
from
django.test
import
TestCase
from
django.test
import
TestCase
from
rest_framework
import
serializers
from
rest_framework
import
serializers
from
rest_framework.tests.models
import
ForeignKeyTarget
,
ForeignKeySource
,
NullableForeignKeySource
,
OneToOneTarget
,
NullableOneToOneSource
class
ForeignKeySourceSerializer
(
serializers
.
ModelSerializer
):
class
OneToOneTarget
(
models
.
Model
):
class
Meta
:
name
=
models
.
CharField
(
max_length
=
100
)
depth
=
1
model
=
ForeignKeySource
class
FlatForeignKeySourceSerializer
(
serializers
.
ModelSerializer
):
class
Meta
:
model
=
ForeignKeySource
class
OneToOneTargetSource
(
models
.
Model
):
name
=
models
.
CharField
(
max_length
=
100
)
target
=
models
.
OneToOneField
(
OneToOneTarget
,
null
=
True
,
blank
=
True
,
related_name
=
'target_source'
)
class
ForeignKeyTargetSerializer
(
serializers
.
ModelSerializer
):
sources
=
FlatForeignKeySourceSerializer
(
many
=
True
)
class
Meta
:
class
OneToOneSource
(
models
.
Model
):
model
=
ForeignKeyTarget
name
=
models
.
CharField
(
max_length
=
100
)
target_source
=
models
.
OneToOneField
(
OneToOneTargetSource
,
related_name
=
'source'
)
class
NullableForeignKey
SourceSerializer
(
serializers
.
ModelSerializer
):
class
OneToOne
SourceSerializer
(
serializers
.
ModelSerializer
):
class
Meta
:
class
Meta
:
depth
=
1
model
=
OneToOneSource
model
=
NullableForeignKeySource
exclude
=
(
'target_source'
,
)
class
NullableOneToOneSourceSerializer
(
serializers
.
ModelSerializer
):
class
OneToOneTargetSourceSerializer
(
serializers
.
ModelSerializer
):
source
=
OneToOneSourceSerializer
()
class
Meta
:
class
Meta
:
model
=
NullableOneToOneSource
model
=
OneToOneTargetSource
exclude
=
(
'target'
,
)
class
Nullable
OneToOneTargetSerializer
(
serializers
.
ModelSerializer
):
class
OneToOneTargetSerializer
(
serializers
.
ModelSerializer
):
nullable_source
=
NullableOneToOne
SourceSerializer
()
target_source
=
OneToOneTarget
SourceSerializer
()
class
Meta
:
class
Meta
:
model
=
OneToOneTarget
model
=
OneToOneTarget
class
ReverseForeignKey
Tests
(
TestCase
):
class
NestedOneToOne
Tests
(
TestCase
):
def
setUp
(
self
):
def
setUp
(
self
):
target
=
ForeignKeyTarget
(
name
=
'target-1'
)
target
.
save
()
new_target
=
ForeignKeyTarget
(
name
=
'target-2'
)
new_target
.
save
()
for
idx
in
range
(
1
,
4
):
for
idx
in
range
(
1
,
4
):
source
=
ForeignKeySource
(
name
=
'source-
%
d'
%
idx
,
target
=
target
)
target
=
OneToOneTarget
(
name
=
'target-
%
d'
%
idx
)
target
.
save
()
target_source
=
OneToOneTargetSource
(
name
=
'target-source-
%
d'
%
idx
,
target
=
target
)
target_source
.
save
()
source
=
OneToOneSource
(
name
=
'source-
%
d'
%
idx
,
target_source
=
target_source
)
source
.
save
()
source
.
save
()
def
test_
foreign_key
_retrieve
(
self
):
def
test_
one_to_one
_retrieve
(
self
):
queryset
=
ForeignKeySource
.
objects
.
all
()
queryset
=
OneToOneTarget
.
objects
.
all
()
serializer
=
ForeignKeySourceSerializer
(
queryset
,
many
=
True
)
serializer
=
OneToOneTargetSerializer
(
queryset
)
expected
=
[
expected
=
[
{
'id'
:
1
,
'name'
:
'
source-1'
,
'target'
:
{
'id'
:
1
,
'name'
:
'target-1'
}},
{
'id'
:
1
,
'name'
:
'
target-1'
,
'target_source'
:
{
'id'
:
1
,
'name'
:
'target-source-1'
,
'source'
:
{
'id'
:
1
,
'name'
:
'source-1'
}
}},
{
'id'
:
2
,
'name'
:
'
source-2'
,
'target'
:
{
'id'
:
1
,
'name'
:
'target-1'
}},
{
'id'
:
2
,
'name'
:
'
target-2'
,
'target_source'
:
{
'id'
:
2
,
'name'
:
'target-source-2'
,
'source'
:
{
'id'
:
2
,
'name'
:
'source-2'
}
}},
{
'id'
:
3
,
'name'
:
'
source-3'
,
'target'
:
{
'id'
:
1
,
'name'
:
'target-1'
}},
{
'id'
:
3
,
'name'
:
'
target-3'
,
'target_source'
:
{
'id'
:
3
,
'name'
:
'target-source-3'
,
'source'
:
{
'id'
:
3
,
'name'
:
'source-3'
}}}
]
]
self
.
assertEqual
(
serializer
.
data
,
expected
)
self
.
assertEqual
(
serializer
.
data
,
expected
)
def
test_reverse_foreign_key_retrieve
(
self
):
def
test_one_to_one_create
(
self
):
queryset
=
ForeignKeyTarget
.
objects
.
all
()
data
=
{
'id'
:
4
,
'name'
:
'target-4'
,
'target_source'
:
{
'id'
:
4
,
'name'
:
'target-source-4'
,
'source'
:
{
'id'
:
4
,
'name'
:
'source-4'
}}}
serializer
=
ForeignKeyTargetSerializer
(
queryset
,
many
=
True
)
serializer
=
OneToOneTargetSerializer
(
data
=
data
)
self
.
assertTrue
(
serializer
.
is_valid
())
obj
=
serializer
.
save
()
self
.
assertEqual
(
serializer
.
data
,
data
)
self
.
assertEqual
(
obj
.
name
,
'target-4'
)
# Ensure (target 4, target_source 4, source 4) are added, and
# everything else is as expected.
queryset
=
OneToOneTarget
.
objects
.
all
()
serializer
=
OneToOneTargetSerializer
(
queryset
)
expected
=
[
expected
=
[
{
'id'
:
1
,
'name'
:
'target-1'
,
'sources'
:
[
{
'id'
:
1
,
'name'
:
'target-1'
,
'target_source'
:
{
'id'
:
1
,
'name'
:
'target-source-1'
,
'source'
:
{
'id'
:
1
,
'name'
:
'source-1'
}}},
{
'id'
:
1
,
'name'
:
'source-1'
,
'target'
:
1
},
{
'id'
:
2
,
'name'
:
'target-2'
,
'target_source'
:
{
'id'
:
2
,
'name'
:
'target-source-2'
,
'source'
:
{
'id'
:
2
,
'name'
:
'source-2'
}}},
{
'id'
:
2
,
'name'
:
'source-2'
,
'target'
:
1
},
{
'id'
:
3
,
'name'
:
'target-3'
,
'target_source'
:
{
'id'
:
3
,
'name'
:
'target-source-3'
,
'source'
:
{
'id'
:
3
,
'name'
:
'source-3'
}}},
{
'id'
:
3
,
'name'
:
'source-3'
,
'target'
:
1
},
{
'id'
:
4
,
'name'
:
'target-4'
,
'target_source'
:
{
'id'
:
4
,
'name'
:
'target-source-4'
,
'source'
:
{
'id'
:
4
,
'name'
:
'source-4'
}}}
]},
{
'id'
:
2
,
'name'
:
'target-2'
,
'sources'
:
[
]}
]
]
self
.
assertEqual
(
serializer
.
data
,
expected
)
self
.
assertEqual
(
serializer
.
data
,
expected
)
def
test_one_to_one_create_with_invalid_data
(
self
):
class
NestedNullableForeignKeyTests
(
TestCase
):
data
=
{
'id'
:
4
,
'name'
:
'target-4'
,
'target_source'
:
{
'id'
:
4
,
'name'
:
'target-source-4'
,
'source'
:
{
'id'
:
4
}}}
def
setUp
(
self
):
serializer
=
OneToOneTargetSerializer
(
data
=
data
)
target
=
ForeignKeyTarget
(
name
=
'target-1'
)
self
.
assertFalse
(
serializer
.
is_valid
())
target
.
save
()
self
.
assertEqual
(
serializer
.
errors
,
{
'target_source'
:
[{
'source'
:
[{
'name'
:
[
'This field is required.'
]}]}]})
for
idx
in
range
(
1
,
4
):
if
idx
==
3
:
def
test_one_to_one_update
(
self
):
target
=
None
data
=
{
'id'
:
3
,
'name'
:
'target-3-updated'
,
'target_source'
:
{
'id'
:
3
,
'name'
:
'target-source-3-updated'
,
'source'
:
{
'id'
:
3
,
'name'
:
'source-3-updated'
}}}
source
=
NullableForeignKeySource
(
name
=
'source-
%
d'
%
idx
,
target
=
target
)
instance
=
OneToOneTarget
.
objects
.
get
(
pk
=
3
)
source
.
save
()
serializer
=
OneToOneTargetSerializer
(
instance
,
data
=
data
)
self
.
assertTrue
(
serializer
.
is_valid
())
def
test_foreign_key_retrieve_with_null
(
self
):
obj
=
serializer
.
save
()
queryset
=
NullableForeignKeySource
.
objects
.
all
()
self
.
assertEqual
(
serializer
.
data
,
data
)
serializer
=
NullableForeignKeySourceSerializer
(
queryset
,
many
=
True
)
self
.
assertEqual
(
obj
.
name
,
'target-3-updated'
)
# Ensure (target 3, target_source 3, source 3) are updated,
# and everything else is as expected.
queryset
=
OneToOneTarget
.
objects
.
all
()
serializer
=
OneToOneTargetSerializer
(
queryset
)
expected
=
[
expected
=
[
{
'id'
:
1
,
'name'
:
'
source-1'
,
'target'
:
{
'id'
:
1
,
'name'
:
'target-1'
}},
{
'id'
:
1
,
'name'
:
'
target-1'
,
'target_source'
:
{
'id'
:
1
,
'name'
:
'target-source-1'
,
'source'
:
{
'id'
:
1
,
'name'
:
'source-1'
}
}},
{
'id'
:
2
,
'name'
:
'
source-2'
,
'target'
:
{
'id'
:
1
,
'name'
:
'target-1'
}},
{
'id'
:
2
,
'name'
:
'
target-2'
,
'target_source'
:
{
'id'
:
2
,
'name'
:
'target-source-2'
,
'source'
:
{
'id'
:
2
,
'name'
:
'source-2'
}
}},
{
'id'
:
3
,
'name'
:
'
source-3'
,
'target'
:
None
},
{
'id'
:
3
,
'name'
:
'
target-3-updated'
,
'target_source'
:
{
'id'
:
3
,
'name'
:
'target-source-3-updated'
,
'source'
:
{
'id'
:
3
,
'name'
:
'source-3-updated'
}}}
]
]
self
.
assertEqual
(
serializer
.
data
,
expected
)
self
.
assertEqual
(
serializer
.
data
,
expected
)
def
test_one_to_one_delete
(
self
):
data
=
{
'id'
:
3
,
'name'
:
'target-3'
,
'target_source'
:
None
}
instance
=
OneToOneTarget
.
objects
.
get
(
pk
=
3
)
serializer
=
OneToOneTargetSerializer
(
instance
,
data
=
data
)
self
.
assertTrue
(
serializer
.
is_valid
())
serializer
.
save
()
class
NestedNullableOneToOneTests
(
TestCase
):
# Ensure (target_source 3, source 3) are deleted,
def
setUp
(
self
):
# and everything else is as expected.
target
=
OneToOneTarget
(
name
=
'target-1'
)
target
.
save
()
new_target
=
OneToOneTarget
(
name
=
'target-2'
)
new_target
.
save
()
source
=
NullableOneToOneSource
(
name
=
'source-1'
,
target
=
target
)
source
.
save
()
def
test_reverse_foreign_key_retrieve_with_null
(
self
):
queryset
=
OneToOneTarget
.
objects
.
all
()
queryset
=
OneToOneTarget
.
objects
.
all
()
serializer
=
NullableOneToOneTargetSerializer
(
queryset
,
many
=
True
)
serializer
=
OneToOneTargetSerializer
(
queryset
)
expected
=
[
expected
=
[
{
'id'
:
1
,
'name'
:
'target-1'
,
'nullable_source'
:
{
'id'
:
1
,
'name'
:
'source-1'
,
'target'
:
1
}},
{
'id'
:
1
,
'name'
:
'target-1'
,
'target_source'
:
{
'id'
:
1
,
'name'
:
'target-source-1'
,
'source'
:
{
'id'
:
1
,
'name'
:
'source-1'
}}},
{
'id'
:
2
,
'name'
:
'target-2'
,
'nullable_source'
:
None
},
{
'id'
:
2
,
'name'
:
'target-2'
,
'target_source'
:
{
'id'
:
2
,
'name'
:
'target-source-2'
,
'source'
:
{
'id'
:
2
,
'name'
:
'source-2'
}}},
{
'id'
:
3
,
'name'
:
'target-3'
,
'target_source'
:
None
}
]
]
self
.
assertEqual
(
serializer
.
data
,
expected
)
self
.
assertEqual
(
serializer
.
data
,
expected
)
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