예제 #1
0
 def to_internal_value(self, data):
     if not data or not data.startswith("data:"):
         raise serializers.SkipField()
     mime_type, file_data = parse_base64_data_uri(data)
     file_format = mime_type.split("/")[1]
     filename = f"{self.field_name}-avatar.{file_format}"
     return ContentFile(file_data, name=filename)
예제 #2
0
    def validate_empty_values(self, column):
        """
        Validate empty values, and either:

        * Raise `ValidationError`, indicating invalid data.
        * Raise `SkipField`, indicating that the field should be ignored.
        * Return (True, data), indicating an empty value that should be
          returned without any further validation being applied.
        * Return (False, data), indicating a non-empty value, that should
          have validation applied as normal.
        """
        if self.read_only:
            return True, self.get_default()

        if column is serializers.empty:
            if getattr(self.root, 'partial', False):
                raise serializers.SkipField()
            if self.required:
                self.fail('required')
            return True, self.get_default()

        if column.isnull().any():
            if not self.allow_null:
                self.fail('null')
            # Nullable `source='*'` fields should not be skipped when its named
            # field is given a null value. This is because `source='*'` means
            # the field is passed the entire object, which is not null.
            elif self.source == '*':
                return False, column
            return False, column

        return False, column
예제 #3
0
 def validate_group(self, group: Group):
     # Make sure the group doesn't change
     if self.instance:
         if group and self.instance.group_id != group.group_id:
             raise serializers.ValidationError("Group may not be changed")
         # just skip this field, no need to change it
         raise serializers.SkipField()
     return group
예제 #4
0
 def __call__(self, serializer_field):
     is_many = getattr(serializer_field.root, 'many', False)
     if is_many:
         raise serializers.SkipField()
     if callable(self.default):
         if getattr(self.default, 'requires_context', False):
             return self.default(serializer_field)
         else:
             return self.default()
     return self.default
예제 #5
0
    def to_internal_value(self, data):
        if isinstance(data, six.string_types) and data.isdigit():
            data = int(data)

        try:
            value = self.enum.get(data).value
        except AttributeError:  # .get() returned None
            if not self.required:
                raise serializers.SkipField()
            self.fail("invalid_choice", input=data)

        return value
예제 #6
0
    def to_internal_value(self, value):
        '''
        This is a hack to do some pre-validation. The building of the
        GenericRelations must be done in the view itself
        b/c it needs access to the saved instance.
        '''
        import json
        if value:
            try:
                entities = json.loads(value)
            except Exception:
                raise serializers.ValidationError('Error parsing JSON')

            for child in entities:
                try:
                    overlay_type = child['overlay_type']
                    ids = child['ids']
                except Exception:
                    raise serializers.ValidationError(
                        '%s must have an overlay_type and an ids attribute' %
                        child)
                if not isinstance(ids, list):
                    raise serializers.ValidationError('%s must be a list' %
                                                      ids)

                for id in ids:
                    # ensure that the requested child item exists:
                    from localground.apps.site.models import Base
                    try:
                        obj = Base.get_model(
                            model_name=overlay_type).objects.get(id=id)
                    except Exception:
                        raise serializers.ValidationError(
                            'No %s object exists with id=%s' %
                            (overlay_type, id))
        # this exception prevents the 'entities' dictionary from being
        # directly applied to the entities many-to-many (which is impossible)
        # to specify before the object has been created.
        raise serializers.SkipField()
예제 #7
0
 def validate_empty_values(self, data):
     raise serializers.SkipField()
예제 #8
0
 def __call__(self):
     if not self.is_update:
         raise serializers.SkipField()
     if callable(self.default):
         return self.default()
     return self.default
예제 #9
0
 def to_internal_value(self, value):
     if getattr(self, 'encrypted', False) and isinstance(
             value, str) and value.startswith('$encrypted$'):
         raise serializers.SkipField()
     obj = super(SettingFieldMixin, self).to_internal_value(value)
     return super(SettingFieldMixin, self).to_representation(obj)
예제 #10
0
        def inner_validate_method(self, value):
            if 'action' not in self.context:
                raise serializers.SkipField()

            return validate_method(self, value, self.context['action'])
예제 #11
0
 def get_attribute(self, instance):
     raise serializers.SkipField()
예제 #12
0
    def to_internal_value(self, data):
        if not isinstance(data, list):
            message = self.error_messages['not_a_list'].format(input_type=type(data).__name__)
            raise serializers.ValidationError({api_settings.NON_FIELD_ERRORS_KEY: [message]}, code='not_a_list')

        if not self.allow_empty and len(data) == 0:
            if self.parent and self.partial:
                raise serializers.SkipField()
            else:
                self.fail('empty')

        ret = []
        errors = []
        partial = self.partial

        # build look-up objects for instances and data, so we can look them up with their keys
        try:
            known_instances = {(x.subname, x.type): x for x in self.instance}
        except TypeError:  # in case self.instance is None (as during POST)
            known_instances = {}
        indices_by_key = {}
        for idx, item in enumerate(data):
            # Validate item type before using anything from it
            if not isinstance(item, dict):
                self.fail('invalid', datatype=type(item).__name__)
            items = indices_by_key.setdefault(self._key(item), set())
            items.add(idx)

        # Iterate over all rows in the data given
        for idx, item in enumerate(data):
            try:
                # see if other rows have the same key
                if len(indices_by_key[self._key(item)]) > 1:
                    raise serializers.ValidationError({
                        'non_field_errors': [
                            'Same subname and type as in position(s) %s, but must be unique.' %
                            ', '.join(map(str, indices_by_key[self._key(item)] - {idx}))
                        ]
                    })

                # determine if this is a partial update (i.e. PATCH):
                # we allow partial update if a partial update method (i.e. PATCH) is used, as indicated by self.partial,
                # and if this is not actually a create request because it is unknown and nonempty
                unknown = self._key(item) not in known_instances.keys()
                nonempty = item.get('records', None) != []
                self.partial = partial and not (unknown and nonempty)
                self.child.instance = known_instances.get(self._key(item), None)

                # with partial value and instance in place, let the validation begin!
                validated = self.child.run_validation(item)
            except serializers.ValidationError as exc:
                errors.append(exc.detail)
            else:
                ret.append(validated)
                errors.append({})

        self.partial = partial

        if any(errors):
            raise serializers.ValidationError(errors)

        return ret
예제 #13
0
 def __call__(self):
     if self.is_many:
         raise serializers.SkipField()
     if callable(self.default):
         return self.default()
     return self.default
예제 #14
0
    def to_internal_value(self, data):
        if not isinstance(data, list):
            message = self.error_messages['not_a_list'].format(input_type=type(data).__name__)
            raise serializers.ValidationError({api_settings.NON_FIELD_ERRORS_KEY: [message]}, code='not_a_list')

        if not self.allow_empty and len(data) == 0:
            if self.parent and self.partial:
                raise serializers.SkipField()
            else:
                self.fail('empty')

        ret = []
        errors = []
        partial = self.partial

        # build look-up objects for instances and data, so we can look them up with their keys
        try:
            known_instances = {(x.subname, x.type): x for x in self.instance}
        except TypeError:  # in case self.instance is None (as during POST)
            known_instances = {}
        indices = {}
        for idx, item in enumerate(data):
            # Validate item type before using anything from it
            if not isinstance(item, dict):
                self.fail('invalid', datatype=type(item).__name__)
            s, t = self._key(item)  # subname, type
            # Construct an index of the RRsets in `data` by `s` and `t`. As (subname, type) may be given multiple times
            # (although invalid), we make indices[s][t] a set to properly keep track. We also check and record RRsets
            # which are known in the database (once per subname), using index `None` (for checking CNAME exclusivity).
            if s not in indices:
                types = self.child.domain.rrset_set.filter(subname=s).values_list('type', flat=True)
                indices[s] = {type_: {None} for type_ in types}
            items = indices[s].setdefault(t, set())
            items.add(idx)

        collapsed_indices = copy.deepcopy(indices)
        for idx, item in enumerate(data):
            if item.get('records') == []:
                s, t = self._key(item)
                collapsed_indices[s][t] -= {idx, None}

        # Iterate over all rows in the data given
        for idx, item in enumerate(data):
            try:
                # see if other rows have the same key
                s, t = self._key(item)
                data_indices = indices[s][t] - {None}
                if len(data_indices) > 1:
                    raise serializers.ValidationError({
                        'non_field_errors': [
                            'Same subname and type as in position(s) %s, but must be unique.' %
                            ', '.join(map(str, data_indices - {idx}))
                        ]
                    })

                # see if other rows violate CNAME exclusivity
                if item.get('records') != []:
                    conflicting_indices_by_type = {k: v for k, v in collapsed_indices[s].items()
                                                   if (k == 'CNAME') != (t == 'CNAME')}
                    if any(conflicting_indices_by_type.values()):
                        types_by_position = self._types_by_position_string(conflicting_indices_by_type)
                        raise serializers.ValidationError({
                            'non_field_errors': [
                                f'RRset with conflicting type present: {types_by_position}.'
                                ' (No other RRsets are allowed alongside CNAME.)'
                            ]
                        })

                # determine if this is a partial update (i.e. PATCH):
                # we allow partial update if a partial update method (i.e. PATCH) is used, as indicated by self.partial,
                # and if this is not actually a create request because it is unknown and nonempty
                unknown = self._key(item) not in known_instances.keys()
                nonempty = item.get('records', None) != []
                self.partial = partial and not (unknown and nonempty)
                self.child.instance = known_instances.get(self._key(item), None)

                # with partial value and instance in place, let the validation begin!
                validated = self.child.run_validation(item)
            except serializers.ValidationError as exc:
                errors.append(exc.detail)
            else:
                ret.append(validated)
                errors.append({})

        self.partial = partial

        if any(errors):
            raise serializers.ValidationError(errors)

        return ret
예제 #15
0
 def get_attribute(self, instance):
     if self.source == 'payment.from_account' and instance.value < 0 \
             or self.source == 'payment.to_account' and instance.value > 0:
         raise serializers.SkipField()
     return super().get_attribute(instance)