diff options
| author | Tom Christie | 2013-03-22 17:01:06 +0000 | 
|---|---|---|
| committer | Tom Christie | 2013-03-22 17:01:06 +0000 | 
| commit | 13794baf7016f7d44daffb55d29e3dbc56f7612d (patch) | |
| tree | c330b1ab6eb5d7a66011e995ee8a75405eade0d5 /rest_framework/serializers.py | |
| parent | b4210f9a56fb7f8913f674aecb304da01e2e9f64 (diff) | |
| download | django-rest-framework-13794baf7016f7d44daffb55d29e3dbc56f7612d.tar.bz2 | |
Bit of extra tidying and plenty of docs
Diffstat (limited to 'rest_framework/serializers.py')
| -rw-r--r-- | rest_framework/serializers.py | 49 | 
1 files changed, 33 insertions, 16 deletions
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 3029cf1c..0b0c2c9c 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -110,13 +110,15 @@ class BaseSerializer(Field):      _dict_class = SortedDictWithMetadata      def __init__(self, instance=None, data=None, files=None, -                 context=None, partial=False, many=None, source=None): +                 context=None, partial=False, many=None, source=None, +                 allow_delete=False):          super(BaseSerializer, self).__init__(source=source)          self.opts = self._options_class(self.Meta)          self.parent = None          self.root = None          self.partial = partial          self.many = many +        self.allow_delete = allow_delete          self.context = context or {} @@ -130,6 +132,12 @@ class BaseSerializer(Field):          self._errors = None          self._deleted = None +        if many and instance is not None and not hasattr(instance, '__iter__'): +            raise ValueError('instance should be a queryset or other iterable with many=True') + +        if allow_delete and not many: +            raise ValueError('allow_delete should only be used for bulk updates, but you have not set many=True') +      #####      # Methods to determine which fields to use when (de)serializing objects. @@ -336,8 +344,15 @@ class BaseSerializer(Field):          """          This hook is required for bulk update.          It is used to determine the canonical identity of a given object. + +        Note that the data has not been validated at this point, so we need +        to make sure that we catch any cases of incorrect datatypes being +        passed to this method.          """ -        return data.get('id') +        try: +            return data.get('id', None) +        except AttributeError: +            return None      @property      def errors(self): @@ -371,22 +386,12 @@ class BaseSerializer(Field):                      identities = [self.get_identity(self.to_native(obj)) for obj in objects]                      identity_to_objects = dict(zip(identities, objects)) -                try: -                    iter(data) -                    if isinstance(data, dict): -                        raise TypeError -                except TypeError: -                    self._errors = {'non_field_errors': ['Expected a list of items']} -                else: +                if hasattr(data, '__iter__') and not isinstance(data, (dict, six.text_type)):                      for item in data:                          if update:                              # Determine which object we're updating -                            try: -                                identity = self.get_identity(item) -                            except: -                                self.object = None -                            else: -                                self.object = identity_to_objects.pop(identity, None) +                            identity = self.get_identity(item) +                            self.object = identity_to_objects.pop(identity, None)                          ret.append(self.from_native(item, None))                          errors.append(self._errors) @@ -395,6 +400,8 @@ class BaseSerializer(Field):                          self._deleted = identity_to_objects.values()                      self._errors = any(errors) and errors or [] +                else: +                    self._errors = {'non_field_errors': ['Expected a list of items']}              else:                  ret = self.from_native(data, files) @@ -445,7 +452,7 @@ class BaseSerializer(Field):          else:              self.save_object(self.object, **kwargs) -        if self._deleted: +        if self.allow_delete and self._deleted:              [self.delete_object(item) for item in self._deleted]          return self.object @@ -736,3 +743,13 @@ class HyperlinkedModelSerializer(ModelSerializer):              'many': to_many          }          return HyperlinkedRelatedField(**kwargs) + +    def get_identity(self, data): +        """ +        This hook is required for bulk update. +        We need to override the default, to use the url as the identity. +        """ +        try: +            return data.get('url', None) +        except AttributeError: +            return None  | 
