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
598e5877
Commit
598e5877
authored
Jun 16, 2017
by
Tom Christie
Committed by
GitHub
Jun 16, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #5192 from matteius/DRF-5135-one-to-one-pk
Special case for when OneToOneField is also primary key.
parents
d48a745f
88f9dbce
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
70 additions
and
2 deletions
+70
-2
rest_framework/serializers.py
+5
-0
tests/models.py
+8
-0
tests/test_relations_pk.py
+57
-2
No files found.
rest_framework/serializers.py
View file @
598e5877
...
...
@@ -1159,6 +1159,11 @@ class ModelSerializer(Serializer):
field_class
=
field_mapping
[
model_field
]
field_kwargs
=
get_field_kwargs
(
field_name
,
model_field
)
# Special case to handle when a OneToOneField is also the primary key
if
model_field
.
one_to_one
and
model_field
.
primary_key
:
field_class
=
self
.
serializer_related_field
field_kwargs
[
'queryset'
]
=
model_field
.
related_model
.
objects
if
'choices'
in
field_kwargs
:
# Fields with choices get coerced into `ChoiceField`
# instead of using their regular typed field.
...
...
tests/models.py
View file @
598e5877
...
...
@@ -88,3 +88,11 @@ class NullableOneToOneSource(RESTFrameworkModel):
target
=
models
.
OneToOneField
(
OneToOneTarget
,
null
=
True
,
blank
=
True
,
related_name
=
'nullable_source'
,
on_delete
=
models
.
CASCADE
)
class
OneToOnePKSource
(
RESTFrameworkModel
):
""" Test model where the primary key is a OneToOneField with another model. """
name
=
models
.
CharField
(
max_length
=
100
)
target
=
models
.
OneToOneField
(
OneToOneTarget
,
primary_key
=
True
,
related_name
=
'required_source'
,
on_delete
=
models
.
CASCADE
)
tests/test_relations_pk.py
View file @
598e5877
...
...
@@ -6,8 +6,8 @@ from django.utils import six
from
rest_framework
import
serializers
from
tests.models
import
(
ForeignKeySource
,
ForeignKeyTarget
,
ManyToManySource
,
ManyToManyTarget
,
NullableForeignKeySource
,
NullableOneToOneSource
,
NullableUUIDForeignKey
Source
,
OneToOneTarget
,
UUIDForeignKeyTarget
NullableForeignKeySource
,
NullableOneToOneSource
,
NullableUUIDForeignKeySource
,
OneToOnePK
Source
,
OneToOneTarget
,
UUIDForeignKeyTarget
)
...
...
@@ -63,6 +63,13 @@ class NullableOneToOneTargetSerializer(serializers.ModelSerializer):
fields
=
(
'id'
,
'name'
,
'nullable_source'
)
class
OneToOnePKSourceSerializer
(
serializers
.
ModelSerializer
):
class
Meta
:
model
=
OneToOnePKSource
fields
=
'__all__'
# TODO: Add test that .data cannot be accessed prior to .is_valid
class
PKManyToManyTests
(
TestCase
):
...
...
@@ -486,3 +493,51 @@ class PKNullableOneToOneTests(TestCase):
{
'id'
:
2
,
'name'
:
'target-2'
,
'nullable_source'
:
1
},
]
assert
serializer
.
data
==
expected
class
OneToOnePrimaryKeyTests
(
TestCase
):
def
setUp
(
self
):
# Given: Some target models already exist
self
.
target
=
target
=
OneToOneTarget
(
name
=
'target-1'
)
target
.
save
()
self
.
alt_target
=
alt_target
=
OneToOneTarget
(
name
=
'target-2'
)
alt_target
.
save
()
def
test_one_to_one_when_primary_key
(
self
):
# When: Creating a Source pointing at the id of the second Target
target_pk
=
self
.
alt_target
.
id
source
=
OneToOnePKSourceSerializer
(
data
=
{
'name'
:
'source-2'
,
'target'
:
target_pk
})
# Then: The source is valid with the serializer
if
not
source
.
is_valid
():
self
.
fail
(
"Expected OneToOnePKTargetSerializer to be valid but had errors: {}"
.
format
(
source
.
errors
))
# Then: Saving the serializer creates a new object
new_source
=
source
.
save
()
# Then: The new object has the same pk as the target object
self
.
assertEqual
(
new_source
.
pk
,
target_pk
)
def
test_one_to_one_when_primary_key_no_duplicates
(
self
):
# When: Creating a Source pointing at the id of the second Target
target_pk
=
self
.
target
.
id
data
=
{
'name'
:
'source-1'
,
'target'
:
target_pk
}
source
=
OneToOnePKSourceSerializer
(
data
=
data
)
# Then: The source is valid with the serializer
self
.
assertTrue
(
source
.
is_valid
())
# Then: Saving the serializer creates a new object
new_source
=
source
.
save
()
# Then: The new object has the same pk as the target object
self
.
assertEqual
(
new_source
.
pk
,
target_pk
)
# When: Trying to create a second object
second_source
=
OneToOnePKSourceSerializer
(
data
=
data
)
self
.
assertFalse
(
second_source
.
is_valid
())
expected
=
{
'target'
:
[
u'one to one pk source with this target already exists.'
]}
self
.
assertDictEqual
(
second_source
.
errors
,
expected
)
def
test_one_to_one_when_primary_key_does_not_exist
(
self
):
# Given: a target PK that does not exist
target_pk
=
self
.
target
.
pk
+
self
.
alt_target
.
pk
source
=
OneToOnePKSourceSerializer
(
data
=
{
'name'
:
'source-2'
,
'target'
:
target_pk
})
# Then: The source is not valid with the serializer
self
.
assertFalse
(
source
.
is_valid
())
self
.
assertIn
(
"Invalid pk"
,
source
.
errors
[
'target'
][
0
])
self
.
assertIn
(
"object does not exist"
,
source
.
errors
[
'target'
][
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