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
1148b25c
Commit
1148b25c
authored
Apr 19, 2013
by
Tom Christie
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #796 from maspwr/writable-nested-modelserializer
Fix model serializer nestesd delete behavior
parents
eceae648
fdc5cc3d
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
32 additions
and
25 deletions
+32
-25
rest_framework/serializers.py
+13
-25
rest_framework/tests/relations_nested.py
+19
-0
No files found.
rest_framework/serializers.py
View file @
1148b25c
...
@@ -20,6 +20,9 @@ from rest_framework.relations import *
...
@@ -20,6 +20,9 @@ from rest_framework.relations import *
from
rest_framework.fields
import
*
from
rest_framework.fields
import
*
class
RelationsList
(
list
):
_deleted
=
[]
class
NestedValidationError
(
ValidationError
):
class
NestedValidationError
(
ValidationError
):
"""
"""
The default ValidationError behavior is to stringify each item in the list
The default ValidationError behavior is to stringify each item in the list
...
@@ -149,7 +152,6 @@ class BaseSerializer(WritableField):
...
@@ -149,7 +152,6 @@ class BaseSerializer(WritableField):
self
.
_data
=
None
self
.
_data
=
None
self
.
_files
=
None
self
.
_files
=
None
self
.
_errors
=
None
self
.
_errors
=
None
self
.
_deleted
=
None
if
many
and
instance
is
not
None
and
not
hasattr
(
instance
,
'__iter__'
):
if
many
and
instance
is
not
None
and
not
hasattr
(
instance
,
'__iter__'
):
raise
ValueError
(
'instance should be a queryset or other iterable with many=True'
)
raise
ValueError
(
'instance should be a queryset or other iterable with many=True'
)
...
@@ -288,15 +290,8 @@ class BaseSerializer(WritableField):
...
@@ -288,15 +290,8 @@ class BaseSerializer(WritableField):
You should override this method to control how deserialized objects
You should override this method to control how deserialized objects
are instantiated.
are instantiated.
"""
"""
removed_relations
=
[]
# Deleted related objects
if
self
.
_deleted
:
removed_relations
=
list
(
self
.
_deleted
)
if
instance
is
not
None
:
if
instance
is
not
None
:
instance
.
update
(
attrs
)
instance
.
update
(
attrs
)
instance
.
_removed_relations
=
removed_relations
return
instance
return
instance
return
attrs
return
attrs
...
@@ -438,7 +433,7 @@ class BaseSerializer(WritableField):
...
@@ -438,7 +433,7 @@ class BaseSerializer(WritableField):
PendingDeprecationWarning
,
stacklevel
=
3
)
PendingDeprecationWarning
,
stacklevel
=
3
)
if
many
:
if
many
:
ret
=
[]
ret
=
RelationsList
()
errors
=
[]
errors
=
[]
update
=
self
.
object
is
not
None
update
=
self
.
object
is
not
None
...
@@ -466,7 +461,7 @@ class BaseSerializer(WritableField):
...
@@ -466,7 +461,7 @@ class BaseSerializer(WritableField):
errors
.
append
(
self
.
_errors
)
errors
.
append
(
self
.
_errors
)
if
update
:
if
update
:
self
.
_deleted
=
identity_to_objects
.
values
()
ret
.
_deleted
=
identity_to_objects
.
values
()
self
.
_errors
=
any
(
errors
)
and
errors
or
[]
self
.
_errors
=
any
(
errors
)
and
errors
or
[]
else
:
else
:
...
@@ -509,9 +504,6 @@ class BaseSerializer(WritableField):
...
@@ -509,9 +504,6 @@ class BaseSerializer(WritableField):
def
save_object
(
self
,
obj
,
**
kwargs
):
def
save_object
(
self
,
obj
,
**
kwargs
):
obj
.
save
(
**
kwargs
)
obj
.
save
(
**
kwargs
)
if
self
.
allow_add_remove
and
hasattr
(
obj
,
'_removed_relations'
):
[
self
.
delete_object
(
item
)
for
item
in
obj
.
_removed_relations
]
def
delete_object
(
self
,
obj
):
def
delete_object
(
self
,
obj
):
obj
.
delete
()
obj
.
delete
()
...
@@ -521,12 +513,12 @@ class BaseSerializer(WritableField):
...
@@ -521,12 +513,12 @@ class BaseSerializer(WritableField):
"""
"""
if
isinstance
(
self
.
object
,
list
):
if
isinstance
(
self
.
object
,
list
):
[
self
.
save_object
(
item
,
**
kwargs
)
for
item
in
self
.
object
]
[
self
.
save_object
(
item
,
**
kwargs
)
for
item
in
self
.
object
]
if
self
.
allow_add_remove
and
self
.
object
.
_deleted
:
[
self
.
delete_object
(
item
)
for
item
in
self
.
object
.
_deleted
]
else
:
else
:
self
.
save_object
(
self
.
object
,
**
kwargs
)
self
.
save_object
(
self
.
object
,
**
kwargs
)
if
self
.
allow_add_remove
and
self
.
_deleted
:
[
self
.
delete_object
(
item
)
for
item
in
self
.
_deleted
]
return
self
.
object
return
self
.
object
...
@@ -715,7 +707,6 @@ class ModelSerializer(Serializer):
...
@@ -715,7 +707,6 @@ class ModelSerializer(Serializer):
m2m_data
=
{}
m2m_data
=
{}
related_data
=
{}
related_data
=
{}
nested_forward_relations
=
{}
nested_forward_relations
=
{}
removed_relations
=
[]
meta
=
self
.
opts
.
model
.
_meta
meta
=
self
.
opts
.
model
.
_meta
# Reverse fk or one-to-one relations
# Reverse fk or one-to-one relations
...
@@ -741,10 +732,6 @@ class ModelSerializer(Serializer):
...
@@ -741,10 +732,6 @@ class ModelSerializer(Serializer):
if
isinstance
(
self
.
fields
.
get
(
field_name
,
None
),
Serializer
):
if
isinstance
(
self
.
fields
.
get
(
field_name
,
None
),
Serializer
):
nested_forward_relations
[
field_name
]
=
attrs
[
field_name
]
nested_forward_relations
[
field_name
]
=
attrs
[
field_name
]
# Deleted related objects
if
self
.
_deleted
:
removed_relations
=
list
(
self
.
_deleted
)
# Update an existing instance...
# Update an existing instance...
if
instance
is
not
None
:
if
instance
is
not
None
:
for
key
,
val
in
attrs
.
items
():
for
key
,
val
in
attrs
.
items
():
...
@@ -761,7 +748,6 @@ class ModelSerializer(Serializer):
...
@@ -761,7 +748,6 @@ class ModelSerializer(Serializer):
instance
.
_related_data
=
related_data
instance
.
_related_data
=
related_data
instance
.
_m2m_data
=
m2m_data
instance
.
_m2m_data
=
m2m_data
instance
.
_nested_forward_relations
=
nested_forward_relations
instance
.
_nested_forward_relations
=
nested_forward_relations
instance
.
_removed_relations
=
removed_relations
return
instance
return
instance
...
@@ -786,9 +772,6 @@ class ModelSerializer(Serializer):
...
@@ -786,9 +772,6 @@ class ModelSerializer(Serializer):
obj
.
save
(
**
kwargs
)
obj
.
save
(
**
kwargs
)
if
self
.
allow_add_remove
and
hasattr
(
obj
,
'_removed_relations'
):
[
self
.
delete_object
(
item
)
for
item
in
obj
.
_removed_relations
]
if
getattr
(
obj
,
'_m2m_data'
,
None
):
if
getattr
(
obj
,
'_m2m_data'
,
None
):
for
accessor_name
,
object_list
in
obj
.
_m2m_data
.
items
():
for
accessor_name
,
object_list
in
obj
.
_m2m_data
.
items
():
setattr
(
obj
,
accessor_name
,
object_list
)
setattr
(
obj
,
accessor_name
,
object_list
)
...
@@ -804,6 +787,11 @@ class ModelSerializer(Serializer):
...
@@ -804,6 +787,11 @@ class ModelSerializer(Serializer):
fk_field
=
obj
.
_meta
.
get_field_by_name
(
accessor_name
)[
0
]
.
field
.
name
fk_field
=
obj
.
_meta
.
get_field_by_name
(
accessor_name
)[
0
]
.
field
.
name
setattr
(
related_item
,
fk_field
,
obj
)
setattr
(
related_item
,
fk_field
,
obj
)
self
.
save_object
(
related_item
)
self
.
save_object
(
related_item
)
# Delete any removed objects
if
field
.
allow_add_remove
and
related
.
_deleted
:
[
self
.
delete_object
(
item
)
for
item
in
related
.
_deleted
]
else
:
else
:
# Nested reverse one-one relationship
# Nested reverse one-one relationship
fk_field
=
obj
.
_meta
.
get_field_by_name
(
accessor_name
)[
0
]
.
field
.
name
fk_field
=
obj
.
_meta
.
get_field_by_name
(
accessor_name
)[
0
]
.
field
.
name
...
...
rest_framework/tests/relations_nested.py
View file @
1148b25c
...
@@ -287,3 +287,22 @@ class ReverseNestedOneToManyTests(TestCase):
...
@@ -287,3 +287,22 @@ class ReverseNestedOneToManyTests(TestCase):
]
]
self
.
assertEqual
(
serializer
.
data
,
expected
)
self
.
assertEqual
(
serializer
.
data
,
expected
)
def
test_one_to_many_delete
(
self
):
data
=
{
'id'
:
1
,
'name'
:
'target-1'
,
'sources'
:
[{
'id'
:
1
,
'name'
:
'source-1'
},
{
'id'
:
3
,
'name'
:
'source-3'
}]}
instance
=
OneToManyTarget
.
objects
.
get
(
pk
=
1
)
serializer
=
self
.
Serializer
(
instance
,
data
=
data
)
self
.
assertTrue
(
serializer
.
is_valid
())
serializer
.
save
()
# Ensure source 2 is deleted, and everything else is as
# expected.
queryset
=
OneToManyTarget
.
objects
.
all
()
serializer
=
self
.
Serializer
(
queryset
)
expected
=
[
{
'id'
:
1
,
'name'
:
'target-1'
,
'sources'
:
[{
'id'
:
1
,
'name'
:
'source-1'
},
{
'id'
:
3
,
'name'
:
'source-3'
}]}
]
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