Skip to content
Merged
Changes from 1 commit
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
abe5dd0
Created stubs for unit-tests on EmbeddedDocument customization.
BurkovBA May 8, 2017
e487a81
Mapping tests stubs for fields and exclude.
BurkovBA May 8, 2017
42fb5fd
Stubs of expectations for mapping tests.
BurkovBA May 9, 2017
b3d4429
Copy-pasted get_field_names() from DRF - will modify it.
BurkovBA May 9, 2017
252078e
Replaced single quotes with double quotes around docstrings.
BurkovBA May 9, 2017
7ac417b
Fixed get_field_names(): model_info -> info.
BurkovBA May 10, 2017
d198ade
Renamed fn -> field_name.
BurkovBA May 10, 2017
cc39704
Added nested reference to the tests.
BurkovBA May 16, 2017
ded7760
#215 Basic implementetaion of get_customization_for_nested_field.
BurkovBA May 21, 2017
63e2ef3
#215 Improvements to get_customization_for_nested_field.
BurkovBA May 23, 2017
3ecd34f
#215 Created Customization namedtuple, moved some code around.
BurkovBA May 24, 2017
fc2a5da
#215 Added customization to embedded and nested_reference serializers.
BurkovBA May 24, 2017
d63361f
#215 Bugfix in get_customization...(): extra_kwargs is a dict, not l…
BurkovBA May 25, 2017
19b6fcf
#215 Created apply_customization() with common logic for embedded an…
BurkovBA May 27, 2017
52db731
#215 Fixing failing tests.
BurkovBA May 28, 2017
30e1b9c
#215 Fixed if-else logic in get_field_names() to ignore child fields.
BurkovBA May 28, 2017
85ae83d
#215 Fixed failing unit-test mappings, fixed pyflakes/isort errors.
BurkovBA May 28, 2017
869d5da
#215 Fixes in customization for compound fields.
BurkovBA May 29, 2017
aef0256
#215 Fixed broken tests: read_only -> read_only_fields.
BurkovBA May 30, 2017
2b51ab8
#215 Changes to repr.
BurkovBA Jun 1, 2017
c5432cb
#215 Fixed bugs in repr for DictField.
BurkovBA Jun 1, 2017
d3c04f0
#215 Unit-tests for list_of_embedded_documents.
BurkovBA Jun 2, 2017
2c2a224
#215 Stub for integration tests.
BurkovBA Jun 3, 2017
64f600c
#215 TestEmbeddedCustomizationFieldsIntegration done.
BurkovBA Jun 4, 2017
66fe78b
#215 TestEmbeddedCustomizationExcludeIntegration done.
BurkovBA Jun 4, 2017
6f7727b
#215 TestEmbeddedCustomizationReadOnlyIntegration done.
BurkovBA Jun 5, 2017
ed594a2
#215 TestEmbeddedCustomizationExtraFieldKwargsIntegration done.
BurkovBA Jun 5, 2017
ff4ba0d
#215 TestEmbeddedCustomizationValidateMethodIntegration done.
BurkovBA Jun 6, 2017
8cef6a1
#215 Renamed tests to TestNestedCustomization...
BurkovBA Jun 6, 2017
6ac9fe0
#215 TestNestedCompoundCustomizationFieldsIntegration done.
BurkovBA Jun 7, 2017
f466962
#215 TestNestedCompoundCustomizationExcludeIntegration done.
BurkovBA Jun 7, 2017
5efd37e
#215 TestNestedCompoundCustomizationReadOnlyIntegration done.
BurkovBA Jun 7, 2017
d968151
#215 TestNestedCompoundCustomizationExtraFieldKwargsIntegration done.
BurkovBA Jun 7, 2017
d05b031
#215 TestNestedCompoundCustomizationValidateMethodIntegration done, …
BurkovBA Jun 8, 2017
4462dec
#215 Bug in test fixed.
BurkovBA Jun 9, 2017
0b7d169
Merge branch 'master' of https://github.com/umutbozkurt/django-rest-f…
BurkovBA Jun 10, 2017
c0bf3c2
Linebreaks to keep linter happy.
BurkovBA Jun 10, 2017
49605ed
Merge branch '215-nested-extra-kwargs'
BurkovBA Jun 10, 2017
318dfa4
Fixed import for python3.5 and isort.
BurkovBA Jun 10, 2017
2298dde
im_func -> __func__ for python3 compatibility
BurkovBA Jun 10, 2017
49c7cce
Used six.get_unbound_function for compat with python3.
BurkovBA Jun 10, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
#215 Created Customization namedtuple, moved some code around.
  • Loading branch information
BurkovBA committed May 24, 2017
commit 3ecd34fc6022caeb3ec58e9cccde1815a09be3e0
87 changes: 48 additions & 39 deletions rest_framework_mongoengine/serializers.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import copy
from collections import OrderedDict
from collections import OrderedDict, namedtuple
import warnings

from mongoengine import fields as me_fields
from mongoengine.errors import ValidationError as me_ValidationError
from rest_framework import fields as drf_fields
from rest_framework import serializers
from rest_framework.compat import unicode_to_repr
from rest_framework.serializers import ALL_FIELDS
from rest_framework.utils.field_mapping import ClassLookupDict

from rest_framework_mongoengine import fields as drfm_fields
Expand All @@ -23,7 +24,14 @@
)


ALL_FIELDS = '__all__'
# This object is used for customization of nested field attributes in DocumentSerializer
Customization = namedtuple("Customization", [
'fields',
'exclude',
'extra_kwargs',
'validate_methods'
])


def raise_errors_on_nested_writes(method_name, serializer, validated_data):
# *** inherited from DRF 3, altered for EmbeddedDocumentSerializer to pass ***
Expand Down Expand Up @@ -444,41 +452,6 @@ def get_default_field_names(self, declared_fields, model_info):
list(model_info.embedded.keys())
)

def build_field(self, field_name, info, model_class, nested_depth, embedded_depth):
if field_name in info.fields_and_pk:
model_field = info.fields_and_pk[field_name]
if isinstance(model_field, COMPOUND_FIELD_TYPES):
child_name = field_name + '.child'
if child_name in info.fields or child_name in info.embedded or child_name in info.references:
child_class, child_kwargs = self.build_field(child_name, info, model_class, nested_depth, embedded_depth)
child_field = child_class(**child_kwargs)
else:
child_field = None
return self.build_compound_field(field_name, model_field, child_field)
else:
return self.build_standard_field(field_name, model_field)

if field_name in info.references:
relation_info = info.references[field_name]
if nested_depth and relation_info.related_model:
return self.build_nested_reference_field(field_name, relation_info, nested_depth)
else:
return self.build_reference_field(field_name, relation_info, nested_depth)

if field_name in info.embedded:
relation_info = info.embedded[field_name]
if not relation_info.related_model:
return self.build_generic_embedded_field(field_name, relation_info, embedded_depth)
if embedded_depth:
return self.build_nested_embedded_field(field_name, relation_info, embedded_depth)
else:
return self.build_bottom_embedded_field(field_name, relation_info, embedded_depth)

if hasattr(model_class, field_name):
return self.build_property_field(field_name, model_class)

return self.build_unknown_field(field_name, model_class)

def get_customization_for_nested_field(self, field_name):
""" Support of nested fields customization for:
* EmbeddedDocumentField
Expand Down Expand Up @@ -520,12 +493,48 @@ def get_customization_for_nested_field(self, field_name):
# get nested_extra_kwargs
nested_extra_kwargs = [field.split('.', 1)[1] for field in self.extra_kwargs if field.startswith(field_name + '.')]

# get nested_validate_methods dict {name: function}, rename e.g. 'validate_author__age()' -> v'alidate_age()'
# get nested_validate_methods dict {name: function}, rename e.g. 'validate_author__age()' -> 'validate_age()'
# so that we can add them to nested serializer's definition under this new name
# validate_methods are normally checked in rest_framework.Serializer.to_internal_value()
nested_validate_methods = {attr: getattr(self, attr) for attr in dir(self) if attr.startswith('validate_%s__' % field_name)}
nested_validate_methods = {'validate_' + attr.split('__', 1)[1]: value for attr, value in nested_validate_methods }

return nested_fields, nested_exclude, nested_extra_kwargs, nested_validate_methods
return Customization(nested_fields, nested_exclude, nested_extra_kwargs, nested_validate_methods)

def build_field(self, field_name, info, model_class, nested_depth, embedded_depth):
if field_name in info.fields_and_pk:
model_field = info.fields_and_pk[field_name]
if isinstance(model_field, COMPOUND_FIELD_TYPES):
child_name = field_name + '.child'
if child_name in info.fields or child_name in info.embedded or child_name in info.references:
child_class, child_kwargs = self.build_field(child_name, info, model_class, nested_depth, embedded_depth)
child_field = child_class(**child_kwargs)
else:
child_field = None
return self.build_compound_field(field_name, model_field, child_field)
else:
return self.build_standard_field(field_name, model_field)

if field_name in info.references:
relation_info = info.references[field_name]
if nested_depth and relation_info.related_model:
return self.build_nested_reference_field(field_name, relation_info, nested_depth)
else:
return self.build_reference_field(field_name, relation_info, nested_depth)

if field_name in info.embedded:
relation_info = info.embedded[field_name]
if not relation_info.related_model:
return self.build_generic_embedded_field(field_name, relation_info, embedded_depth)
if embedded_depth:
return self.build_nested_embedded_field(field_name, relation_info, embedded_depth)
else:
return self.build_bottom_embedded_field(field_name, relation_info, embedded_depth)

if hasattr(model_class, field_name):
return self.build_property_field(field_name, model_class)

return self.build_unknown_field(field_name, model_class)

def build_standard_field(self, field_name, model_field):
field_mapping = ClassLookupDict(self.serializer_field_mapping)
Expand Down