Exemplo n.º 1
0
def _get_attribute(self, instance):
    # Can't have any relationships if not created
    if hasattr(instance, 'pk') and instance.pk is None:
        return []

    try:
        relationship = get_attribute(instance, self.source_attrs)
    except (KeyError, AttributeError) as exc:
        if self.default is not empty:
            return self.get_default()
        if self.allow_null:
            return None
        if not self.required:
            raise SkipField()
        msg = ('Got {exc_type} when attempting to get a value for field '
               '`{field}` on serializer `{serializer}`.\nThe serializer '
               'field might be named incorrectly and not match '
               'any attribute or key on the `{instance}` instance.\n'
               'Original exception text was: {exc}.'.format(
                   exc_type=type(exc).__name__,
                   field=self.field_name,
                   serializer=self.parent.__class__.__name__,
                   instance=instance.__class__.__name__,
                   exc=exc,
               ))
        raise type(exc)(msg)

    return relationship.all() if hasattr(relationship, 'all') else relationship
Exemplo n.º 2
0
    def to_internal_value(self, data):
        # Skip http/https urls to avoid overwriting valid data when, for example, a client GETs and subsequently PUTs an
        # entity containing an image URL.
        if self.skip_http and not isinstance(data, UploadedFile) and urlparse.urlparse(data).scheme in ('http', 'https'):
            raise SkipField()

        return super(ValidImageField, self).to_internal_value(data)
Exemplo n.º 3
0
        def to_internal_value(self, data):
            required = kwargs.get('required', True)
            default = kwargs.get('default', empty)

            if data == empty:
                # Implementation under this block is made
                # according to DRF behaviour to other normal fields
                # For more details see
                # https://www.django-rest-framework.org/api-guide/fields/#required
                # https://www.django-rest-framework.org/api-guide/fields/#default
                # https://www.django-rest-framework.org/api-guide/fields/#allow_null
                if self.root.partial or not required:
                    # Skip the field because the update is partial
                    # or the field is not required(optional)
                    raise SkipField()
                elif required:
                    if default == empty:
                        raise ValidationError(
                            "This field is required.",
                            code='required'
                        )
                    else:
                        # Use the default value
                        data = default

            if accept_pk_only:
                return self.run_pk_validation(data)
            elif accept_pk:
                if isinstance(data, dict):
                    self.is_replaceable = False
                    return self.run_data_validation(data)
                else:
                    return self.run_pk_validation(data)
            return self.run_data_validation(data)
Exemplo n.º 4
0
    def to_representation(self, instance):
        request = self._get_request()
        fields = self._readable_fields
        ret = OrderedDict()

        # Get fields that the user is allowed to view.
        allowed_fields = self.Meta.field_permissions.get_permitted_field_names(
            action='view', obj=instance, user=request.user)

        # Skip fields that the user is not allowed to view. Use the SkipField
        # exception because `field.get_attribute` can also raise that.
        for field in fields:
            try:
                if field.field_name not in allowed_fields:
                    raise SkipField()

                attribute = field.get_attribute(instance)
            except SkipField:
                continue

            # Filter related objects that are None as we don't have to serialize
            # them.
            check_for_none = attribute.pk if isinstance(attribute, PKOnlyObject) else attribute
            ret[field.field_name] = None if check_for_none is None else field.to_representation(attribute)

        return ret
Exemplo n.º 5
0
    def get_attribute(self, instance):
        value = serializers.Field.get_attribute(self, instance)

        if value == '' or value is None or value == {}:
            if not self.required or not self.allow_blank:
                raise SkipField()
        return value
Exemplo n.º 6
0
    def validate_empty_values(self, data):
        """
        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 data is empty:
            if getattr(self.root, "partial", False):
                raise SkipField()
            if self.required:
                self.fail("required")
            return (True, self.get_default())

        if data is None:
            if not self.allow_null:
                raise serializers.ValidationError(
                    strings.Addresses.NULL_COUNTRY)
            # 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, None)
            return (True, None)

        return (False, data)
Exemplo n.º 7
0
    def to_representation(self, instance, row_data=None):
        """
        Object instance -> Dict of primitive datatypes.
        """
        ret = OrderedDict()
        for field in self._readable_fields:
            try:
                attribute = field.get_attribute(instance)
                if not isinstance(field, RenderMixin):
                    ret[field.field_name] = field.to_representation(attribute)
                else:
                    try:
                        ret[field.field_name] = field.to_representation(
                            attribute, instance)
                    except:
                        if attribute is None and not field.required:
                            # DRF makes a special check for none and then always returns None if the check is None.
                            # We still want to process custom field to_representation, even if value is None.
                            # But when field is a sub-serializer and it (it's FK reference) is none, it's OK
                            # to pass None as result of serialization of such field
                            raise SkipField()
                        else:
                            raise
            except SkipField:
                pass

        return ret
Exemplo n.º 8
0
 def __call__(self):
     if hasattr(self, 'is_update') and self.is_update:
         # TODO: Make sure this check is sufficient for all update scenarios
         raise SkipField()
     user = super(CreateOnlyCurrentUserDefault, self).__call__()
     if user and user.is_authenticated():
         return user
     return None
Exemplo n.º 9
0
 def enforce_required_fields(self, attrs, serializer):
     try:
         super(OptionalUniqueTogetherValidator, self).enforce_required_fields(attrs, serializer)
     except ValidationError as e:
         if set(e.detail.keys()) == set(self.fields):
             raise SkipField()
         else:
             raise
Exemplo n.º 10
0
    def to_internal_value(self, data):
        """
        List of dicts of native values <- List of dicts of primitive datatypes.
        """
        if not self.instance:
            return super().to_internal_value(data)

        if html.is_html_input(data):
            data = html.parse_html_list(data)

        if not isinstance(data, list):
            message = self.error_messages['not_a_list'].format(
                input_type=type(data).__name__
            )
            raise 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 SkipField()

            message = self.error_messages['empty']
            raise ValidationError({
                api_settings.NON_FIELD_ERRORS_KEY: [message]
            }, code='empty')

        ret = []
        errors = []

        for item in data:
            try:
                # prepare child serializer to only handle one instance
                if 'id' in item:
                    pk = item["id"]
                elif 'pk' in item:
                    pk = item["pk"]
                else:
                    raise ValidationError("id or pk not in data")
                child = self.instance.get(id=pk) if self.instance else None
                self.child.instance = child
                self.child.initial_data = item
                # raw
                validated = self.child.run_validation(item)
            except ValidationError as exc:
                errors.append(exc.detail)
            except ObjectDoesNotExist as e:
                errors.append(e)
            else:
                ret.append(validated)
                errors.append({})

        if any(errors):
            raise ValidationError(errors)

        return ret
Exemplo n.º 11
0
    def get_attribute(self, instance):
        # When handling the create() all, skip this field.
        if isinstance(instance, (dict, OrderedDict)):
            raise SkipField()

        assert isinstance(instance, TranslatedFieldsModel), ((
            "The TranslatedAbsoluteUrlField can only be used on a TranslatableModelSerializer, "
            " not on a {0}".format(instance.__class__)))

        return instance
Exemplo n.º 12
0
 def run_validation(self, data):
     # Reject empty strings only if field is required.
     # Otherwise SkipField on encountering an empty string.
     if data == '':
         if not self.allow_blank and not self.required:
             raise SkipField()
         elif not self.allow_blank:
             self.fail('blank')
         return ''
     return super(serializers.CharField, self).run_validation(data)
Exemplo n.º 13
0
    def to_internal_value(self, data):
        # Skip http/https urls to avoid overwriting valid data when, for example, a client GETs and subsequently PUTs an
        # entity containing an image URL.
        if self.skip_http and not isinstance(
                data, UploadedFile) and urllib.parse.urlparse(data).scheme in (
                    'http', 'https'):
            raise SkipField()

        self.source_attrs = [
            'image'
        ]  # Kind of a dirty hack, because this is failing to stick if set on init.
        return super(ValidImageField, self).to_internal_value(data)
Exemplo n.º 14
0
    def to_internal_value(self, obj):
        if obj in self.EMPTY_VALUES:
            return None
        elif isinstance(obj, str):
            if obj.startswith('http'):
                raise SkipField()
            media_url = getattr(settings, 'MEDIA_URL', None)
            if media_url and obj.startswith(media_url):
                raise SkipField()
        elif isinstance(obj, dict):
            if not all(key in obj for key in ('file_name', 'encoded_str')):
                raise ValidationError(self.INVALID_OBJECT)
            try:
                self.name, self.ext = obj['file_name'].rsplit('.', 1)
            except ValueError:
                raise ValidationError(self.INVALID_FILE_NAME)

            if self.ext not in self.ALLOWED_TYPES and self.ALLOW_ALL_EXTENSIONS:
                self.ALLOWED_TYPES.append(self.ext)

            encoded_str = obj['encoded_str']
            return super().to_internal_value(encoded_str)
        elif isinstance(obj, UploadedFile):
            try:
                self.name = obj.name
                self.size = obj.size
            except AttributeError:
                raise ValidationError(self.INVALID_FILE_UPLOAD)

            try:
                _, self.ext = self.name.rsplit('.', 1)
            except ValueError:
                raise ValidationError(self.INVALID_FILE_NAME)

            if self.ext not in self.ALLOWED_TYPES and not self.ALLOW_ALL_EXTENSIONS:
                raise ValidationError(self.INVALID_TYPE_MESSAGE)

            return obj
        else:
            raise ValidationError(self.INVALID_DATA)
Exemplo n.º 15
0
    def validate_empty_values(self, data):
        """
        If an empty value (empty string, null) exists in an optional
        field, SkipField.
        """
        (is_empty_value, data) = serializers.Field.validate_empty_values(self, data)

        if is_empty_value or data == '':
            if self.required:
                self.fail('required')
            raise SkipField()

        return (False, data)
Exemplo n.º 16
0
    def run_validation(self, data=empty):
        """
        We override the default `run_validation`, because the validation
        performed by validators and the `.validate()` method should
        be coerced into an error dictionary with a 'non_fields_error' key.
        """
        if data is empty:
            if getattr(self.root, 'partial', False):
                raise SkipField()
            if self.required:
                self.fail('required')
            return self.get_default()

        if data is None:
            if not self.allow_null:
                self.fail('null')
            return None

        if not isinstance(data, dict):
            message = self.error_messages['invalid'].format(
                datatype=type(data).__name__)
            raise ValidationError(
                {api_settings.NON_FIELD_ERRORS_KEY: [message]})

        value = self.to_internal_value(data)
        try:
            self.run_validators(value)
            value = self.validate(value)
            assert value is not None, '.validate() should return the validated data'
        except ValidationError as exc:
            if isinstance(exc.detail, dict):
                # .validate() errors may be a dict, in which case, use
                # standard {key: list of values} style.
                raise ValidationError(
                    dict([(key, value if isinstance(value, list) else [value])
                          for key, value in exc.detail.items()]))
            elif isinstance(exc.detail, list):
                raise ValidationError(
                    {api_settings.NON_FIELD_ERRORS_KEY: exc.detail})
            else:
                raise ValidationError(
                    {api_settings.NON_FIELD_ERRORS_KEY: [exc.detail]})
        except DjangoValidationError as exc:
            # Normally you should raise `serializers.ValidationError`
            # inside your codebase, but we handle Django's validation
            # exception class as well for simpler compat.
            # Eg. Calling Model.clean() explictily inside Serializer.validate()
            raise ValidationError(
                {api_settings.NON_FIELD_ERRORS_KEY: list(exc.messages)})

        return value
Exemplo n.º 17
0
    def to_internal_value(self, data):
        if not isinstance(data, str):
            raise ValidationError("uploaded-file-invalid-uploaded-file")

        try:
            uuid.UUID(data)
            return self.fetch_file_or_error(data)
        except ValueError:
            if not data.startswith("http://") and not data.startswith(
                    "https://"):
                raise ValidationError("uploaded-file-invalid-uuid")

        # Storing the value again, without changes: This is expected to be the original URL
        raise SkipField()
Exemplo n.º 18
0
    def _decode(self, data):
        if is_text(data) and data.startswith('data:'):
            # base64 encoded file - decode
            format, datastr = data.split(';base64,')  # format ~= data:image/X,
            ext = format.split('/')[-1]  # guess file extension
            if ext[:3] == 'svg':
                ext = 'svg'

            data = ContentFile(base64.b64decode(datastr),
                               name='{}.{}'.format(uuid.uuid4(), ext))

        elif is_text(data) and data.startswith('http'):
            raise SkipField()

        return data
Exemplo n.º 19
0
    def validate_empty_values(self, data):
        """
        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 not data or data is empty:
            raise SkipField()

        return super().validate_empty_values(data)
Exemplo n.º 20
0
    def to_internal_value(self, data):
        if not isinstance(data, dict):
            message = self.error_messages['not_a_dict'].format(
                input_type=type(data).__name__)
            raise ValidationError(
                {api_settings.NON_FIELD_ERRORS_KEY: [message]},
                code='not_a_dict')
        if not self.allow_empty and len(data) == 0:
            if self.parent and self.partial:
                raise SkipField()

            message = self.error_messages['empty']
            raise ValidationError(
                {api_settings.NON_FIELD_ERRORS_KEY: [message]}, code='empty')
        data = [{**v, **{self._keyed_field: k}} for k, v in data.items()]
        return super().to_internal_value(data)
    def to_internal_value(self, data):
        """
        List of dicts of native values <- List of dicts of primitive datatypes.
        """
        if html.is_html_input(data):
            data = html.parse_html_list(data)

        if not isinstance(data, list):
            message = self.error_messages['not_a_list'].format(
                input_type=type(data).__name__)
            raise 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 SkipField()

            message = self.error_messages['empty']
            raise ValidationError(
                {api_settings.NON_FIELD_ERRORS_KEY: [message]}, code='empty')

        id_attr = getattr(self.child.Meta, 'update_lookup_field', 'id')
        ret = []
        errors = []

        for item in data:
            try:
                view = self.context.get('view')
                if view and view.action != 'create':
                    if id_attr not in item:
                        raise ValidationError(
                            {id_attr: ['This field is required.']})

                    instance = self.instance.get(**{id_attr: item[id_attr]})

                    self.child.instance = instance
                    self.child.initial_data = item
                # Until here
                validated = self.child.run_validation(item)
            except ValidationError as exc:
                errors.append(exc.detail)
            else:
                ret.append(validated)
                errors.append({})

        return {'ret': ret, 'errors': errors}
Exemplo n.º 22
0
    def to_internal_value(self, data):
        """
        List of dicts of native values <- List of dicts of primitive datatypes.
        """
        if html.is_html_input(data):
            data = html.parse_html_list(data, default=[])

        if not isinstance(data, list):
            message = self.error_messages['not_a_list'].format(
                input_type=type(data).__name__)
            raise 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 SkipField()

            message = self.error_messages['empty']
            raise ValidationError(
                {api_settings.NON_FIELD_ERRORS_KEY: [message]}, code='empty')

        ret = []
        errors = []

        for item in data:
            try:
                if self.instance:
                    try:
                        self.child.instance = self.instance.get(id=item['id'])
                        self.child.initial_data = item
                    except getattr(self.child.Meta.model,
                                   'DoesNotExist') as exc:
                        raise ValidationError({'non_field_errors': [str(exc)]})

                validated = self.child.run_validation(item)
            except ValidationError as exc:
                errors.append(exc.detail)
            else:
                ret.append(validated)
                errors.append({})

        if any(errors):
            raise ValidationError(errors)

        return ret
Exemplo n.º 23
0
 def get_attribute(self, instance):
     try:
         return get_attribute_smart(instance, self.source_attrs)
     except (KeyError, AttributeError) as exc:
         if not self.required and self.default is empty:
             raise SkipField()
         msg = ('Got {exc_type} when attempting to get a value for field '
                '`{field}` on serializer `{serializer}`.\nThe serializer '
                'field might be named incorrectly and not match '
                'any attribute or key on the `{instance}` instance.\n'
                'Original exception text was: {exc}.'.format(
                    exc_type=type(exc).__name__,
                    field=self.field_name,
                    serializer=self.parent.__class__.__name__,
                    instance=instance.__class__.__name__,
                    exc=exc))
         raise type(exc)(msg)
Exemplo n.º 24
0
    def _decode(self, data):
        if isinstance(data, str) and data.startswith("data:"):
            # base64 encoded file - decode
            # format ~= data:image/X,
            format, datastr = data.split(";base64,")
            ext = format.split("/")[-1]  # guess file extension
            if ext[:3] == "svg":
                ext = "svg"

            data = ContentFile(
                base64.b64decode(datastr), name="{}.{}".format(uuid.uuid4(), ext)
            )

        elif isinstance(data, str) and data.startswith("http"):
            raise SkipField()

        return data
Exemplo n.º 25
0
    def to_internal_value(self, data):
        """
        List of dicts of native values <- List of dicts of primitive datatypes.
        """
        if html.is_html_input(data):
            data = html.parse_html_list(data, default=[])

        if not isinstance(data, list):
            message = self.error_messages['not_a_list'].format(
                input_type=type(data).__name__)
            raise 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 SkipField()

            message = self.error_messages['empty']
            raise ValidationError(
                {api_settings.NON_FIELD_ERRORS_KEY: [message]}, code='empty')

        ret = []
        errors = []

        id_attr = getattr(self.child.Meta, 'update_lookup_field', 'id')

        for item in data:
            try:
                # --------------------- patched pieces --------------------------------
                self.child.instance = self.instance.get(
                    **{id_attr: item.get(id_attr)})
                self.child.initial_data = item
                # ---------------------------------------------------------------------
                validated = self.child.run_validation(item)
            except ValidationError as exc:
                errors.append(exc.detail)
            else:
                ret.append(validated)
                errors.append({})

        if any(errors):
            raise ValidationError(errors)

        return ret
Exemplo n.º 26
0
    def to_internal_value(self, data):
        """ Body of run_validation for all data items
        """
        if data is None:
            raise ValidationError('All tasks are empty (None)')

        if not isinstance(data, list):
            raise ValidationError(
                {api_settings.NON_FIELD_ERRORS_KEY: 'not a list'},
                code='not_a_list')

        if not self.allow_empty and len(data) == 0:
            if self.parent and self.partial:
                raise SkipField()
            raise ValidationError({api_settings.NON_FIELD_ERRORS_KEY: 'empty'},
                                  code='empty')

        ret, errors = [], []
        self.annotation_count, self.prediction_count = 0, 0
        for i, item in enumerate(data):
            try:
                validated = self.child.validate(item)
            except ValidationError as exc:
                error = self.format_error(i, exc.detail, item)
                errors.append(error)
                # do not print to user too many errors
                if len(errors) >= 100:
                    errors[99] = '...'
                    break
            else:
                ret.append(validated)
                errors.append({})

                if 'annotations' in item:
                    self.annotation_count += len(item['annotations'])
                if 'predictions' in item:
                    self.prediction_count += len(item['predictions'])

        if any(errors):
            logger.warning("Can't deserialize tasks due to " + str(errors))
            raise ValidationError(errors)

        return ret
Exemplo n.º 27
0
    def to_internal_value(self, obj):
        if obj in self.EMPTY_VALUES:
            return None
        elif isinstance(obj, str) and obj.startswith('http'):
            raise SkipField()
        elif isinstance(obj, dict):
            if not all(key in obj for key in ('file_name', 'encoded_str')):
                raise ValidationError(self.INVALID_OBJECT)

            try:
                self.name, self.ext = obj['file_name'].rsplit('.', 1)
            except ValueError:
                raise ValidationError(self.INVALID_FILE_NAME)

            if self.ext not in self.ALLOWED_TYPES and self.ALLOW_ALL_EXTENSIONS:
                self.ALLOWED_TYPES.append(self.ext)

            encoded_str = obj['encoded_str']
            return super().to_internal_value(encoded_str)
        else:
            raise ValidationError(self.INVALID_DATA)
Exemplo n.º 28
0
    def validate_empty_values(self, data):
        """
        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 data is empty:
            if getattr(self.root, 'partial', False):
                raise SkipField()
            if self.write_field.required:
                self.fail('required')
            return (True, self.get_default())

        if data is None:
            if not self.write_field.allow_null:
                self.fail('null')
            return (True, None)

        return (False, data)
Exemplo n.º 29
0
    def get_attribute(self, instance):
        # xform is not an attribute of the MetaData object
        if instance and isinstance(instance.content_object, XForm):
            return instance.content_object

        raise SkipField()
Exemplo n.º 30
0
    def get_attribute(self, instance):
        val = get_object_id_by_content_type(instance, Instance)
        if val:
            return val

        raise SkipField()