aboutsummaryrefslogtreecommitdiffstats
path: root/rest_framework/serializers.py
diff options
context:
space:
mode:
Diffstat (limited to 'rest_framework/serializers.py')
-rw-r--r--rest_framework/serializers.py59
1 files changed, 40 insertions, 19 deletions
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
index e373cd10..d76658b0 100644
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -12,9 +12,9 @@ response content is handled by parsers and renderers.
"""
from __future__ import unicode_literals
from django.db import models
-from django.db.models.fields import FieldDoesNotExist
+from django.db.models.fields import FieldDoesNotExist, Field as DjangoField
from django.utils.translation import ugettext_lazy as _
-from rest_framework.compat import unicode_to_repr
+from rest_framework.compat import postgres_fields, unicode_to_repr
from rest_framework.utils import model_meta
from rest_framework.utils.field_mapping import (
get_url_kwargs, get_field_kwargs,
@@ -177,7 +177,7 @@ class BaseSerializer(Field):
)
assert hasattr(self, 'initial_data'), (
- 'Cannot call `.is_valid()` as no `data=` keyword argument was'
+ 'Cannot call `.is_valid()` as no `data=` keyword argument was '
'passed when instantiating the serializer instance.'
)
@@ -253,7 +253,7 @@ class SerializerMetaclass(type):
# If this class is subclassing another Serializer, add that Serializer's
# fields. Note that we loop over the bases in *reverse*. This is necessary
# in order to maintain the correct order of fields.
- for base in bases[::-1]:
+ for base in reversed(bases):
if hasattr(base, '_declared_fields'):
fields = list(base._declared_fields.items()) + fields
@@ -633,11 +633,11 @@ def raise_errors_on_nested_writes(method_name, serializer, validated_data):
If we don't do this explicitly they'd get a less helpful error when
calling `.save()` on the serializer.
- We don't *automatically* support these sorts of nested writes brecause
+ We don't *automatically* support these sorts of nested writes because
there are too many ambiguities to define a default behavior.
Eg. Suppose we have a `UserSerializer` with a nested profile. How should
- we handle the case of an update, where the `profile` realtionship does
+ we handle the case of an update, where the `profile` relationship does
not exist? Any of the following might be valid:
* Raise an application error.
@@ -702,6 +702,7 @@ class ModelSerializer(Serializer):
you need you should either declare the extra/differing fields explicitly on
the serializer class, or simply use a `Serializer` class.
"""
+
_field_mapping = ClassLookupDict({
models.AutoField: IntegerField,
models.BigIntegerField: IntegerField,
@@ -724,7 +725,8 @@ class ModelSerializer(Serializer):
models.SmallIntegerField: IntegerField,
models.TextField: CharField,
models.TimeField: TimeField,
- models.URLField: URLField,
+ models.URLField: URLField
+ # Note: Some version-specific mappings also defined below.
})
_related_class = PrimaryKeyRelatedField
@@ -880,8 +882,8 @@ class ModelSerializer(Serializer):
# Retrieve metadata about fields & relationships on the model class.
info = model_meta.get_field_info(model)
- # Use the default set of field names if none is supplied explicitly.
if fields is None:
+ # Use the default set of field names if none is supplied explicitly.
fields = self._get_default_field_names(declared_fields, info)
exclude = getattr(self.Meta, 'exclude', None)
if exclude is not None:
@@ -891,6 +893,23 @@ class ModelSerializer(Serializer):
field_name
)
fields.remove(field_name)
+ else:
+ # Check that any fields declared on the class are
+ # also explicitly included in `Meta.fields`.
+
+ # Note that we ignore any fields that were declared on a parent
+ # class, in order to support only including a subset of fields
+ # when subclassing serializers.
+ declared_field_names = set(declared_fields.keys())
+ for cls in self.__class__.__bases__:
+ declared_field_names -= set(getattr(cls, '_declared_fields', []))
+
+ missing_fields = declared_field_names - set(fields)
+ assert not missing_fields, (
+ 'Field `%s` has been declared on serializer `%s`, but '
+ 'is missing from `Meta.fields`.' %
+ (list(missing_fields)[0], self.__class__.__name__)
+ )
# Determine the set of model fields, and the fields that they map to.
# We actually only need this to deal with the slightly awkward case
@@ -922,6 +941,9 @@ class ModelSerializer(Serializer):
except FieldDoesNotExist:
continue
+ if not isinstance(model_field, DjangoField):
+ continue
+
# Include each of the `unique_for_*` field names.
unique_constraint_names |= set([
model_field.unique_for_date,
@@ -1024,17 +1046,6 @@ class ModelSerializer(Serializer):
(field_name, model.__class__.__name__)
)
- # Check that any fields declared on the class are
- # also explicitly included in `Meta.fields`.
- missing_fields = set(declared_fields.keys()) - set(fields)
- if missing_fields:
- missing_field = list(missing_fields)[0]
- raise ImproperlyConfigured(
- 'Field `%s` has been declared on serializer `%s`, but '
- 'is missing from `Meta.fields`.' %
- (missing_field, self.__class__.__name__)
- )
-
# Populate any kwargs defined in `Meta.extra_kwargs`
extras = extra_kwargs.get(field_name, {})
if extras.get('read_only', False):
@@ -1123,6 +1134,16 @@ class ModelSerializer(Serializer):
return NestedSerializer
+if hasattr(models, 'UUIDField'):
+ ModelSerializer._field_mapping[models.UUIDField] = UUIDField
+
+if postgres_fields:
+ class CharMappingField(DictField):
+ child = CharField()
+
+ ModelSerializer._field_mapping[postgres_fields.HStoreField] = CharMappingField
+
+
class HyperlinkedModelSerializer(ModelSerializer):
"""
A type of `ModelSerializer` that uses hyperlinked relationships instead