Skip to content

Commit 9923300

Browse files
committed
Refactor many
1 parent 78a741b commit 9923300

File tree

2 files changed

+37
-10
lines changed

2 files changed

+37
-10
lines changed

rest_framework/relations.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,17 @@
1010

1111

1212
class PKOnlyObject(object):
13+
"""
14+
This is a mock object, used for when we only need the pk of the object
15+
instance, but still want to return an object with a .pk attribute,
16+
in order to keep the same interface as a regular model instance.
17+
"""
1318
def __init__(self, pk):
1419
self.pk = pk
1520

21+
22+
# We assume that 'validators' are intended for the child serializer,
23+
# rather than the parent serializer.
1624
MANY_RELATION_KWARGS = (
1725
'read_only', 'write_only', 'required', 'default', 'initial', 'source',
1826
'label', 'help_text', 'style', 'error_messages'
@@ -36,13 +44,17 @@ def __new__(cls, *args, **kwargs):
3644
# We override this method in order to automagically create
3745
# `ManyRelatedField` classes instead when `many=True` is set.
3846
if kwargs.pop('many', False):
39-
list_kwargs = {'child_relation': cls(*args, **kwargs)}
40-
for key in kwargs.keys():
41-
if key in MANY_RELATION_KWARGS:
42-
list_kwargs[key] = kwargs[key]
43-
return ManyRelatedField(**list_kwargs)
47+
return cls.many_init(*args, **kwargs)
4448
return super(RelatedField, cls).__new__(cls, *args, **kwargs)
4549

50+
@classmethod
51+
def many_init(cls, *args, **kwargs):
52+
list_kwargs = {'child_relation': cls(*args, **kwargs)}
53+
for key in kwargs.keys():
54+
if key in MANY_RELATION_KWARGS:
55+
list_kwargs[key] = kwargs[key]
56+
return ManyRelatedField(**list_kwargs)
57+
4658
def run_validation(self, data=empty):
4759
# We force empty strings to None values for relational fields.
4860
if data == '':

rest_framework/serializers.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@
4646
from rest_framework.relations import * # NOQA
4747
from rest_framework.fields import * # NOQA
4848

49+
50+
# We assume that 'validators' are intended for the child serializer,
51+
# rather than the parent serializer.
4952
LIST_SERIALIZER_KWARGS = (
5053
'read_only', 'write_only', 'required', 'default', 'initial', 'source',
5154
'label', 'help_text', 'style', 'error_messages',
@@ -73,13 +76,25 @@ def __new__(cls, *args, **kwargs):
7376
# We override this method in order to automagically create
7477
# `ListSerializer` classes instead when `many=True` is set.
7578
if kwargs.pop('many', False):
76-
list_kwargs = {'child': cls(*args, **kwargs)}
77-
for key in kwargs.keys():
78-
if key in LIST_SERIALIZER_KWARGS:
79-
list_kwargs[key] = kwargs[key]
80-
return ListSerializer(*args, **list_kwargs)
79+
return cls.many_init(*args, **kwargs)
8180
return super(BaseSerializer, cls).__new__(cls, *args, **kwargs)
8281

82+
@classmethod
83+
def many_init(cls, *args, **kwargs):
84+
"""
85+
This method implements the creation of a `ListSerializer` parent
86+
class when `many=True` is used. You can customize it if you need to
87+
control which keyword arguments are passed to the parent, and
88+
which are passed to the child.
89+
"""
90+
child_serializer = cls(*args, **kwargs)
91+
list_kwargs = {'child': child_serializer}
92+
list_kwargs.update(dict([
93+
(key, value) for key, value in kwargs.items()
94+
if key in LIST_SERIALIZER_KWARGS
95+
]))
96+
return ListSerializer(*args, **list_kwargs)
97+
8398
def to_internal_value(self, data):
8499
raise NotImplementedError('`to_internal_value()` must be implemented.')
85100

0 commit comments

Comments
 (0)