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
207208fe
Commit
207208fe
authored
Oct 31, 2014
by
Tom Christie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Lazy loading of fields and validators. Closes #1963.
parent
11075d37
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
55 additions
and
31 deletions
+55
-31
rest_framework/fields.py
+19
-2
rest_framework/serializers.py
+15
-21
rest_framework/utils/representation.py
+5
-0
tests/test_fields.py
+2
-2
tests/test_model_serializer.py
+2
-2
tests/test_validators.py
+12
-4
No files found.
rest_framework/fields.py
View file @
207208fe
...
@@ -143,7 +143,7 @@ class Field(object):
...
@@ -143,7 +143,7 @@ class Field(object):
def
__init__
(
self
,
read_only
=
False
,
write_only
=
False
,
def
__init__
(
self
,
read_only
=
False
,
write_only
=
False
,
required
=
None
,
default
=
empty
,
initial
=
empty
,
source
=
None
,
required
=
None
,
default
=
empty
,
initial
=
empty
,
source
=
None
,
label
=
None
,
help_text
=
None
,
style
=
None
,
label
=
None
,
help_text
=
None
,
style
=
None
,
error_messages
=
None
,
validators
=
[]
,
allow_null
=
False
):
error_messages
=
None
,
validators
=
None
,
allow_null
=
False
):
self
.
_creation_counter
=
Field
.
_creation_counter
self
.
_creation_counter
=
Field
.
_creation_counter
Field
.
_creation_counter
+=
1
Field
.
_creation_counter
+=
1
...
@@ -166,9 +166,11 @@ class Field(object):
...
@@ -166,9 +166,11 @@ class Field(object):
self
.
label
=
label
self
.
label
=
label
self
.
help_text
=
help_text
self
.
help_text
=
help_text
self
.
style
=
{}
if
style
is
None
else
style
self
.
style
=
{}
if
style
is
None
else
style
self
.
validators
=
validators
[:]
or
self
.
default_validators
[:]
self
.
allow_null
=
allow_null
self
.
allow_null
=
allow_null
if
validators
is
not
None
:
self
.
validators
=
validators
[:]
# These are set up by `.bind()` when the field is added to a serializer.
# These are set up by `.bind()` when the field is added to a serializer.
self
.
field_name
=
None
self
.
field_name
=
None
self
.
parent
=
None
self
.
parent
=
None
...
@@ -214,6 +216,21 @@ class Field(object):
...
@@ -214,6 +216,21 @@ class Field(object):
else
:
else
:
self
.
source_attrs
=
self
.
source
.
split
(
'.'
)
self
.
source_attrs
=
self
.
source
.
split
(
'.'
)
# .validators is a lazily loaded property, that gets its default
# value from `get_validators`.
@property
def
validators
(
self
):
if
not
hasattr
(
self
,
'_validators'
):
self
.
_validators
=
self
.
get_validators
()
return
self
.
_validators
@validators.setter
def
validators
(
self
,
validators
):
self
.
_validators
=
validators
def
get_validators
(
self
):
return
self
.
default_validators
[:]
def
get_initial
(
self
):
def
get_initial
(
self
):
"""
"""
Return a value to use when the field is being returned as a primitive
Return a value to use when the field is being returned as a primitive
...
...
rest_framework/serializers.py
View file @
207208fe
...
@@ -282,21 +282,23 @@ class SerializerMetaclass(type):
...
@@ -282,21 +282,23 @@ class SerializerMetaclass(type):
@six.add_metaclass
(
SerializerMetaclass
)
@six.add_metaclass
(
SerializerMetaclass
)
class
Serializer
(
BaseSerializer
):
class
Serializer
(
BaseSerializer
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
@property
super
(
Serializer
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
def
fields
(
self
):
if
not
hasattr
(
self
,
'_fields'
):
self
.
_fields
=
BindingDict
(
self
)
for
key
,
value
in
self
.
get_fields
()
.
items
():
self
.
_fields
[
key
]
=
value
return
self
.
_fields
def
get_fields
(
self
):
# Every new serializer is created with a clone of the field instances.
# Every new serializer is created with a clone of the field instances.
# This allows users to dynamically modify the fields on a serializer
# This allows users to dynamically modify the fields on a serializer
# instance without affecting every other serializer class.
# instance without affecting every other serializer class.
self
.
fields
=
BindingDict
(
self
)
for
key
,
value
in
self
.
_get_base_fields
()
.
items
():
self
.
fields
[
key
]
=
value
self
.
validators
=
getattr
(
getattr
(
self
,
'Meta'
,
None
),
'validators'
,
[])
def
_get_base_fields
(
self
):
return
copy
.
deepcopy
(
self
.
_declared_fields
)
return
copy
.
deepcopy
(
self
.
_declared_fields
)
def
get_validators
(
self
):
return
getattr
(
getattr
(
self
,
'Meta'
,
None
),
'validators'
,
[])
def
get_initial
(
self
):
def
get_initial
(
self
):
if
self
.
_initial_data
is
not
None
:
if
self
.
_initial_data
is
not
None
:
return
ReturnDict
([
return
ReturnDict
([
...
@@ -520,14 +522,6 @@ class ModelSerializer(Serializer):
...
@@ -520,14 +522,6 @@ class ModelSerializer(Serializer):
})
})
_related_class
=
PrimaryKeyRelatedField
_related_class
=
PrimaryKeyRelatedField
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
(
ModelSerializer
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
if
'validators'
not
in
kwargs
:
validators
=
self
.
get_default_validators
()
if
validators
:
self
.
validators
.
extend
(
validators
)
self
.
_kwargs
[
'validators'
]
=
validators
def
create
(
self
,
validated_attrs
):
def
create
(
self
,
validated_attrs
):
# Check that the user isn't trying to handle a writable nested field.
# Check that the user isn't trying to handle a writable nested field.
# If we don't do this explicitly they'd likely get a confusing
# If we don't do this explicitly they'd likely get a confusing
...
@@ -578,13 +572,13 @@ class ModelSerializer(Serializer):
...
@@ -578,13 +572,13 @@ class ModelSerializer(Serializer):
instance
.
save
()
instance
.
save
()
return
instance
return
instance
def
get_
default_
validators
(
self
):
def
get_validators
(
self
):
field_names
=
set
([
field_names
=
set
([
field
.
source
for
field
in
self
.
fields
.
values
()
field
.
source
for
field
in
self
.
fields
.
values
()
if
(
field
.
source
!=
'*'
)
and
(
'.'
not
in
field
.
source
)
if
(
field
.
source
!=
'*'
)
and
(
'.'
not
in
field
.
source
)
])
])
validators
=
[]
validators
=
getattr
(
getattr
(
self
,
'Meta'
,
None
),
'validators'
,
[])
model_class
=
self
.
Meta
.
model
model_class
=
self
.
Meta
.
model
# Note that we make sure to check `unique_together` both on the
# Note that we make sure to check `unique_together` both on the
...
@@ -627,7 +621,7 @@ class ModelSerializer(Serializer):
...
@@ -627,7 +621,7 @@ class ModelSerializer(Serializer):
return
validators
return
validators
def
_get_base
_fields
(
self
):
def
get
_fields
(
self
):
declared_fields
=
copy
.
deepcopy
(
self
.
_declared_fields
)
declared_fields
=
copy
.
deepcopy
(
self
.
_declared_fields
)
ret
=
SortedDict
()
ret
=
SortedDict
()
...
...
rest_framework/utils/representation.py
View file @
207208fe
...
@@ -82,6 +82,11 @@ def serializer_repr(serializer, indent, force_many=None):
...
@@ -82,6 +82,11 @@ def serializer_repr(serializer, indent, force_many=None):
ret
+=
field_repr
(
field
.
child_relation
,
force_many
=
field
.
child_relation
)
ret
+=
field_repr
(
field
.
child_relation
,
force_many
=
field
.
child_relation
)
else
:
else
:
ret
+=
field_repr
(
field
)
ret
+=
field_repr
(
field
)
if
serializer
.
validators
:
ret
+=
'
\n
'
+
indent_str
+
'class Meta:'
ret
+=
'
\n
'
+
indent_str
+
' validators = '
+
smart_repr
(
serializer
.
validators
)
return
ret
return
ret
...
...
tests/test_fields.py
View file @
207208fe
...
@@ -85,7 +85,7 @@ class TestSource:
...
@@ -85,7 +85,7 @@ class TestSource:
class
ExampleSerializer
(
serializers
.
Serializer
):
class
ExampleSerializer
(
serializers
.
Serializer
):
example_field
=
serializers
.
CharField
(
source
=
'example_field'
)
example_field
=
serializers
.
CharField
(
source
=
'example_field'
)
with
pytest
.
raises
(
AssertionError
)
as
exc_info
:
with
pytest
.
raises
(
AssertionError
)
as
exc_info
:
ExampleSerializer
()
ExampleSerializer
()
.
fields
assert
str
(
exc_info
.
value
)
==
(
assert
str
(
exc_info
.
value
)
==
(
"It is redundant to specify `source='example_field'` on field "
"It is redundant to specify `source='example_field'` on field "
"'CharField' in serializer 'ExampleSerializer', because it is the "
"'CharField' in serializer 'ExampleSerializer', because it is the "
...
@@ -1018,7 +1018,7 @@ class TestSerializerMethodField:
...
@@ -1018,7 +1018,7 @@ class TestSerializerMethodField:
example_field
=
serializers
.
SerializerMethodField
(
'get_example_field'
)
example_field
=
serializers
.
SerializerMethodField
(
'get_example_field'
)
with
pytest
.
raises
(
AssertionError
)
as
exc_info
:
with
pytest
.
raises
(
AssertionError
)
as
exc_info
:
ExampleSerializer
()
ExampleSerializer
()
.
fields
assert
str
(
exc_info
.
value
)
==
(
assert
str
(
exc_info
.
value
)
==
(
"It is redundant to specify `get_example_field` on "
"It is redundant to specify `get_example_field` on "
"SerializerMethodField 'example_field' in serializer "
"SerializerMethodField 'example_field' in serializer "
...
...
tests/test_model_serializer.py
View file @
207208fe
...
@@ -181,7 +181,7 @@ class TestRegularFieldMappings(TestCase):
...
@@ -181,7 +181,7 @@ class TestRegularFieldMappings(TestCase):
fields
=
(
'auto_field'
,
'invalid'
)
fields
=
(
'auto_field'
,
'invalid'
)
with
self
.
assertRaises
(
ImproperlyConfigured
)
as
excinfo
:
with
self
.
assertRaises
(
ImproperlyConfigured
)
as
excinfo
:
TestSerializer
()
TestSerializer
()
.
fields
expected
=
'Field name `invalid` is not valid for model `ModelBase`.'
expected
=
'Field name `invalid` is not valid for model `ModelBase`.'
assert
str
(
excinfo
.
exception
)
==
expected
assert
str
(
excinfo
.
exception
)
==
expected
...
@@ -198,7 +198,7 @@ class TestRegularFieldMappings(TestCase):
...
@@ -198,7 +198,7 @@ class TestRegularFieldMappings(TestCase):
fields
=
(
'auto_field'
,)
fields
=
(
'auto_field'
,)
with
self
.
assertRaises
(
ImproperlyConfigured
)
as
excinfo
:
with
self
.
assertRaises
(
ImproperlyConfigured
)
as
excinfo
:
TestSerializer
()
TestSerializer
()
.
fields
expected
=
(
expected
=
(
'Field `missing` has been declared on serializer '
'Field `missing` has been declared on serializer '
'`TestSerializer`, but is missing from `Meta.fields`.'
'`TestSerializer`, but is missing from `Meta.fields`.'
...
...
tests/test_validators.py
View file @
207208fe
...
@@ -86,10 +86,12 @@ class TestUniquenessTogetherValidation(TestCase):
...
@@ -86,10 +86,12 @@ class TestUniquenessTogetherValidation(TestCase):
def
test_repr
(
self
):
def
test_repr
(
self
):
serializer
=
UniquenessTogetherSerializer
()
serializer
=
UniquenessTogetherSerializer
()
expected
=
dedent
(
"""
expected
=
dedent
(
"""
UniquenessTogetherSerializer(
validators=[<UniqueTogetherValidator(queryset=UniquenessTogetherModel.objects.all(), fields=('race_name', 'position'))>]
):
UniquenessTogetherSerializer():
id = IntegerField(label='ID', read_only=True)
id = IntegerField(label='ID', read_only=True)
race_name = CharField(max_length=100)
race_name = CharField(max_length=100)
position = IntegerField()
position = IntegerField()
class Meta:
validators = [<UniqueTogetherValidator(queryset=UniquenessTogetherModel.objects.all(), fields=('race_name', 'position'))>]
"""
)
"""
)
assert
repr
(
serializer
)
==
expected
assert
repr
(
serializer
)
==
expected
...
@@ -173,10 +175,12 @@ class TestUniquenessForDateValidation(TestCase):
...
@@ -173,10 +175,12 @@ class TestUniquenessForDateValidation(TestCase):
def
test_repr
(
self
):
def
test_repr
(
self
):
serializer
=
UniqueForDateSerializer
()
serializer
=
UniqueForDateSerializer
()
expected
=
dedent
(
"""
expected
=
dedent
(
"""
UniqueForDateSerializer(
validators=[<UniqueForDateValidator(queryset=UniqueForDateModel.objects.all(), field='slug', date_field='published')>]
):
UniqueForDateSerializer():
id = IntegerField(label='ID', read_only=True)
id = IntegerField(label='ID', read_only=True)
slug = CharField(max_length=100)
slug = CharField(max_length=100)
published = DateField(required=True)
published = DateField(required=True)
class Meta:
validators = [<UniqueForDateValidator(queryset=UniqueForDateModel.objects.all(), field='slug', date_field='published')>]
"""
)
"""
)
assert
repr
(
serializer
)
==
expected
assert
repr
(
serializer
)
==
expected
...
@@ -231,10 +235,12 @@ class TestHiddenFieldUniquenessForDateValidation(TestCase):
...
@@ -231,10 +235,12 @@ class TestHiddenFieldUniquenessForDateValidation(TestCase):
serializer
=
TestSerializer
()
serializer
=
TestSerializer
()
expected
=
dedent
(
"""
expected
=
dedent
(
"""
TestSerializer(
validators=[<UniqueForDateValidator(queryset=HiddenFieldUniqueForDateModel.objects.all(), field='slug', date_field='published')>]
):
TestSerializer():
id = IntegerField(label='ID', read_only=True)
id = IntegerField(label='ID', read_only=True)
slug = CharField(max_length=100)
slug = CharField(max_length=100)
published = HiddenField(default=CreateOnlyDefault(<function now>))
published = HiddenField(default=CreateOnlyDefault(<function now>))
class Meta:
validators = [<UniqueForDateValidator(queryset=HiddenFieldUniqueForDateModel.objects.all(), field='slug', date_field='published')>]
"""
)
"""
)
assert
repr
(
serializer
)
==
expected
assert
repr
(
serializer
)
==
expected
...
@@ -246,9 +252,11 @@ class TestHiddenFieldUniquenessForDateValidation(TestCase):
...
@@ -246,9 +252,11 @@ class TestHiddenFieldUniquenessForDateValidation(TestCase):
serializer
=
TestSerializer
()
serializer
=
TestSerializer
()
expected
=
dedent
(
"""
expected
=
dedent
(
"""
TestSerializer(
validators=[<UniqueForDateValidator(queryset=HiddenFieldUniqueForDateModel.objects.all(), field='slug', date_field='published')>]
):
TestSerializer():
id = IntegerField(label='ID', read_only=True)
id = IntegerField(label='ID', read_only=True)
slug = CharField(max_length=100)
slug = CharField(max_length=100)
published = DateTimeField(default=CreateOnlyDefault(<function now>), read_only=True)
published = DateTimeField(default=CreateOnlyDefault(<function now>), read_only=True)
class Meta:
validators = [<UniqueForDateValidator(queryset=HiddenFieldUniqueForDateModel.objects.all(), field='slug', date_field='published')>]
"""
)
"""
)
assert
repr
(
serializer
)
==
expected
assert
repr
(
serializer
)
==
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