Example #1
0
    def patch(self, *args, **kwargs):

        qs = QSManager(request.args, self.schema)

        schema_kwargs = getattr(self, 'patch_schema_kwargs', dict())
        schema_kwargs.update({'partial': True})

        schema = compute_schema(self.schema, schema_kwargs, qs, qs.include)

        json_data = request.get_json() or {}

        self.before_patch(args, kwargs, data=json_data)
        objs = []
        for data in json_data['data']:
            obj = schema.load({'data': data}).data
            obj['id'] = data['id']
            objs += [obj]

        result_objs = self.update_list(objs, qs, kwargs)

        schema_kwargs.update({'many': True})
        many_schema = compute_schema(self.schema, schema_kwargs, qs,
                                     qs.include)
        result = many_schema.dump(result_objs).data

        self.after_patch(result)

        return (result, 200)
    def post(self, *args, **kwargs):
        """Create an object"""

        qs = QSManager(request.args, self.schema)

        schema = compute_schema(self.schema,
                                getattr(self, 'post_schema_kwargs', dict()),
                                qs, qs.include + self.default_include)

        data = self._validate_schema(args, kwargs, schema)
        if isinstance(data, tuple):
            return data

        self.before_post(args, kwargs, data=data)

        obj = self.create_object(data, kwargs)

        result = schema.dump(obj)

        if result['data'].get('links', {}).get('self'):
            final_result = (result, 201, {
                'Location': result['data']['links']['self']
            })
        else:
            final_result = (result, 201)

        result = self.after_post(final_result)

        return result
Example #3
0
    def get(self, *args, **kwargs):
        """Get a relationship details"""
        self.before_get(args, kwargs)

        relationship_field, model_relationship_field, related_type_, related_id_field = self._get_relationship_data(
        )

        obj, data = self._data_layer.get_relationship(model_relationship_field,
                                                      related_type_,
                                                      related_id_field, kwargs)

        result = {
            'links': {
                'self':
                request.path,
                'related':
                self.schema._declared_fields[relationship_field].
                get_related_url(obj)
            },
            'data': data
        }

        qs = QSManager(request.args, self.schema)
        if qs.include:
            schema = compute_schema(self.schema, dict(), qs, qs.include)

            serialized_obj = schema.dump(obj)
            result['included'] = serialized_obj.data.get('included', dict())

        final_result = self.after_get(result)

        return final_result
Example #4
0
    def get(self, *args, **kwargs):
        """Get a relationship details
        """
        relationship_field, related_type_, related_id_field = self._get_relationship_data()
        related_view = self.schema._declared_fields[relationship_field].related_view
        related_view_kwargs = self.schema._declared_fields[relationship_field].related_view_kwargs

        obj, data = self.data_layer.get_relationship(relationship_field, related_type_, related_id_field, **kwargs)

        for key, value in copy(related_view_kwargs).items():
            if isinstance(value, str) and value.startswith('<') and value.endswith('>'):
                tmp_obj = obj
                for field in value[1:-1].split('.'):
                    tmp_obj = getattr(tmp_obj, field)
                related_view_kwargs[key] = tmp_obj

        result = {'links': {'self': url_for(self.view, **kwargs),
                            'related': url_for(related_view, **related_view_kwargs)},
                  'data': data}

        qs = QSManager(request.args, self.schema)
        if qs.include:
            schema = compute_schema(self.schema, dict(), qs, qs.include)

            serialized_obj = schema.dump(obj)
            result['included'] = serialized_obj.data.get('included', dict())

        return result
Example #5
0
    def get(self, *args, **kwargs):
        """Retrieve a collection of objects"""
        self.before_get(args, kwargs)

        qs = QSManager(request.args, self.schema)

        objects_count, objects = self.get_collection(qs, kwargs)

        schema_kwargs = getattr(self, 'get_schema_kwargs', dict())
        schema_kwargs.update({'many': True})

        self.before_marshmallow(args, kwargs)

        schema = compute_schema(self.schema, schema_kwargs, qs, qs.include)

        result = schema.dump(objects).data

        view_kwargs = request.view_args if getattr(self, 'view_kwargs',
                                                   None) is True else dict()
        add_pagination_links(result, objects_count, qs,
                             url_for(self.view, _external=True, **view_kwargs))

        result.update({'meta': {'count': objects_count}})

        final_result = self.after_get(result)

        return final_result
Example #6
0
    def delete(self, *args, **kwargs):
        """Delete relationship(s)
        """
        json_data = request.get_json()

        relationship_field, related_type_, related_id_field = self._get_relationship_data()

        if 'data' not in json_data:
            raise BadRequest('/data', 'You must provide data with a "data" route node')
        if isinstance(json_data['data'], dict):
            if 'type' not in json_data['data']:
                raise BadRequest('/data/type', 'Missing type in "data" node')
            if 'id' not in json_data['data']:
                raise BadRequest('/data/id', 'Missing id in "data" node')
            if json_data['data']['type'] != related_type_:
                raise InvalidType('/data/type', 'The type field does not match the resource type')
        if isinstance(json_data['data'], list):
            for obj in json_data['data']:
                if 'type' not in obj:
                    raise BadRequest('/data/type', 'Missing type in "data" node')
                if 'id' not in obj:
                    raise BadRequest('/data/id', 'Missing id in "data" node')
                if obj['type'] != related_type_:
                    raise InvalidType('/data/type', 'The type provided does not match the resource type')

        obj_, updated = self.data_layer.delete_relationship(json_data, relationship_field, related_id_field, **kwargs)

        qs = QSManager(request.args, self.schema)
        schema = compute_schema(self.schema, dict(), qs, qs.include)

        status_code = 200 if updated is True else 204

        return schema.dump(obj_), status_code
Example #7
0
    def get(self, *args, **kwargs):
        """Retrieve a collection of objects"""
        self.before_get(args, kwargs)

        qs = QSManager(request.args)

        objects_count, objects = self.get_collection(qs, kwargs)

        schema_kwargs = getattr(self, 'get_schema_kwargs', dict())
        schema_kwargs.update({'many': True})

        schema = compute_schema(self.get_schema(objects, kwargs=kwargs),
                                schema_kwargs,
                                qs,
                                qs.include)

        result = schema.dump(objects).data

        self_url = schema.get_top_level_links(result, many=True)['self']
        add_pagination_links(result,
                             objects_count,
                             qs,
                             self_url)

        result.update({'meta': {'count': objects_count}})

        self.after_get(result)

        return result
Example #8
0
    def post(self, *args, **kwargs):
        """Create an object"""
        json_data = request.get_json() or {}

        qs = QSManager(request.args, self.schema)

        schema = compute_schema(self.schema,
                                getattr(self, 'post_schema_kwargs', dict()),
                                qs, qs.include)

        try:
            if isinstance(json_data['data'], list):
                list_data = []
                errors = None
                for data in json_data['data']:
                    data, obj_errors = schema.load({'data': data})
                    list_data += [data]
            else:
                data, errors = schema.load(json_data)
        except IncorrectTypeError as e:
            errors = e.messages
            for error in errors['errors']:
                error['status'] = '409'
                error['title'] = "Incorrect type"
            return errors, 409
        except ValidationError as e:
            errors = e.messages
            for message in errors['errors']:
                message['status'] = '422'
                message['title'] = "Validation error"
            return errors, 422

        if errors:
            for error in errors['errors']:
                error['status'] = "422"
                error['title'] = "Validation error"
            return errors, 422

        self.before_post(args, kwargs, data=data)
        if isinstance(json_data['data'], list):
            objs = self.create_list(list_data, kwargs)
            result = schema.dump(objs).data
            final_result = (result, 201)
        else:
            obj = self.create_object(data, kwargs)
            result = schema.dump(obj).data

            if result['data'].get('links', {}).get('self'):
                final_result = (result, 201, {
                    'Location': result['data']['links']['self']
                })
            else:
                final_result = (result, 201)

        result = self.after_post(final_result)

        return result
Example #9
0
    def patch(self, *args, **kwargs):
        """Update a relationship"""
        json_data = request.get_json() or {}

        relationship_field, model_relationship_field, related_type_, related_id_field = self._get_relationship_data(
        )

        if 'data' not in json_data:
            raise BadRequest('You must provide data with a "data" route node',
                             source={'pointer': '/data'})
        if isinstance(json_data['data'], dict):
            if 'type' not in json_data['data']:
                raise BadRequest('Missing type in "data" node',
                                 source={'pointer': '/data/type'})
            if 'id' not in json_data['data']:
                raise BadRequest('Missing id in "data" node',
                                 source={'pointer': '/data/id'})
            if json_data['data']['type'] != related_type_:
                raise InvalidType(
                    'The type field does not match the resource type',
                    source={'pointer': '/data/type'})
        if isinstance(json_data['data'], list):
            for obj in json_data['data']:
                if 'type' not in obj:
                    raise BadRequest('Missing type in "data" node',
                                     source={'pointer': '/data/type'})
                if 'id' not in obj:
                    raise BadRequest('Missing id in "data" node',
                                     source={'pointer': '/data/id'})
                if obj['type'] != related_type_:
                    raise InvalidType(
                        'The type provided does not match the resource type',
                        source={'pointer': '/data/type'})

        self.before_patch(args, kwargs, json_data=json_data)

        obj_, updated = self._data_layer.update_relationship(
            json_data, model_relationship_field, related_id_field, kwargs)

        qs = QSManager(request.args, self.schema)
        includes = qs.include
        if relationship_field not in qs.include:
            includes.append(relationship_field)
        schema = compute_schema(self.schema, dict(), qs, includes)

        if updated is False:
            return '', 204

        result = schema.dump(obj_).data
        if result.get('links', {}).get('self') is not None:
            result['links']['self'] = request.path

        self.after_patch(result)

        return result, 200
Example #10
0
    def patch(self, *args, **kwargs):
        """Update an object"""
        json_data = request.get_json() or {}

        qs = QSManager(request.args, self.schema)
        schema_kwargs = getattr(self, 'patch_schema_kwargs', dict())
        schema_kwargs.update({'partial': True})

        self.before_marshmallow(args, kwargs)

        schema = compute_schema(self.schema,
                                schema_kwargs,
                                qs,
                                qs.include)

        try:
            data, errors = schema.load(json_data)
        except IncorrectTypeError as e:
            errors = e.messages
            for error in errors['errors']:
                error['status'] = '409'
                error['title'] = "Incorrect type"
            return errors, 409
        except ValidationError as e:
            errors = e.messages
            for message in errors['errors']:
                message['status'] = '422'
                message['title'] = "Validation error"
            return errors, 422

        if errors:
            for error in errors['errors']:
                error['status'] = "422"
                error['title'] = "Validation error"
            return errors, 422

        if 'id' not in json_data['data']:
            raise BadRequest('Missing id in "data" node',
                             source={'pointer': '/data/id'})
        if json_data['data']['id'] != str(kwargs[self.data_layer.get('url_field', 'id')]):
            raise BadRequest('Value of id does not match the resource identifier in url',
                             source={'pointer': '/data/id'})

        self.before_patch(args, kwargs, data=data)

        obj = self.update_object(data, qs, kwargs)

        result = schema.dump(obj).data

        self.after_patch(result)

        return result
Example #11
0
    def delete(self, *args, **kwargs):
        """Delete relationship(s)
        """
        self.before_delete(args, kwargs)

        json_data = request.get_json()

        relationship_field, model_relationship_field, related_type_, related_id_field = self._get_relationship_data(
        )

        if 'data' not in json_data:
            raise BadRequest('/data',
                             'You must provide data with a "data" route node')
        if isinstance(json_data['data'], dict):
            if 'type' not in json_data['data']:
                raise BadRequest('/data/type', 'Missing type in "data" node')
            if 'id' not in json_data['data']:
                raise BadRequest('/data/id', 'Missing id in "data" node')
            if json_data['data']['type'] != related_type_:
                raise InvalidType(
                    '/data/type',
                    'The type field does not match the resource type')
        if isinstance(json_data['data'], list):
            for obj in json_data['data']:
                if 'type' not in obj:
                    raise BadRequest('/data/type',
                                     'Missing type in "data" node')
                if 'id' not in obj:
                    raise BadRequest('/data/id', 'Missing id in "data" node')
                if obj['type'] != related_type_:
                    raise InvalidType(
                        '/data/type',
                        'The type provided does not match the resource type')

        obj_, updated = self._data_layer.delete_relationship(
            json_data, model_relationship_field, related_id_field, kwargs)

        qs = QSManager(request.args, self.schema)
        includes = qs.include
        if relationship_field not in qs.include:
            includes.append(relationship_field)
        schema = compute_schema(self.schema, dict(), qs, includes)

        status_code = 200 if updated is True else 204
        result = schema.dump(obj_).data
        if result.get('links', {}).get('self') is not None:
            result['links']['self'] = request.path
        self.after_delete(result)
        return result, status_code
Example #12
0
    def get(self, *args, **kwargs):
        """Get object details
        """
        obj = self.data_layer.get_object(**kwargs)

        qs = QSManager(request.args, self.schema)

        schema = compute_schema(self.schema,
                                getattr(self.opts, 'schema_get_kwargs', dict()),
                                qs,
                                qs.include)

        result = schema.dump(obj)

        return result.data
Example #13
0
    def patch(self, *args, **kwargs):
        """Update an object
        """
        json_data = request.get_json()

        qs = QSManager(request.args, self.schema)
        schema_kwargs = getattr(self.opts, 'schema_patch_kwargs', dict())
        schema_kwargs.update({'partial': True})

        schema = compute_schema(self.schema,
                                schema_kwargs,
                                qs,
                                qs.include)

        try:
            data, errors = schema.load(json_data)
        except IncorrectTypeError as e:
            errors = e.messages
            for error in errors['errors']:
                error['status'] = '409'
                error['title'] = "Incorrect type"
            return errors, 409
        except ValidationError as e:
            errors = e.messages
            for message in errors['errors']:
                message['status'] = '422'
                message['title'] = "Validation error"
            return errors, 422

        if errors:
            for error in errors['errors']:
                error['status'] = "422"
                error['title'] = "Validation error"
            return errors, 422

        if 'id' not in json_data['data']:
            raise BadRequest('/data/id', 'Missing id in "data" node')
        if json_data['data']['id'] != str(kwargs[getattr(self.data_layer, 'url_field', 'id')]):
            raise BadRequest('/data/id', 'Value of id does not match the resource identifier in url')

        obj = self.data_layer.get_object(**kwargs)
        updated = self.data_layer.update_object(obj, data, **kwargs)

        result = schema.dump(obj)

        status_code = 200 if updated is True else 204
        return result.data, status_code
Example #14
0
    def post(self, *args, **kwargs):
        """Create an object"""
        json_data = request.get_json() or {}

        qs = QSManager(request.args)

        schema = compute_schema(self.get_schema(json_data, is_load=True, kwargs=kwargs),
                                getattr(self, 'post_schema_kwargs', dict()),
                                qs,
                                qs.include)

        try:
            data, errors = schema.load(json_data)
        except IncorrectTypeError as e:
            errors = e.messages
            for error in errors['errors']:
                error['status'] = '409'
                error['title'] = "Incorrect type"
            return errors, 409
        except ValidationError as e:
            errors = e.messages
            for message in errors['errors']:
                message['status'] = '422'
                message['title'] = "Validation error"
            return errors, 422

        if errors:
            for error in errors['errors']:
                error['status'] = "422"
                error['title'] = "Validation error"
            return errors, 422

        self.before_post(args, kwargs, data=data)

        obj = self.create_object(data, kwargs)

        result = schema.dump(obj).data

        self.after_post(result)

        if result['data'].get('links', {}).get('self'):
            final_result = (result, 201, {'Location': result['data']['links']['self']})
        else:
            final_result = (result, 201)

        return final_result
Example #15
0
    def get(self, *args, **kwargs):
        """Get object details
        """
        self.before_get(args, kwargs)

        obj = self._data_layer.get_object(kwargs)

        qs = QSManager(request.args, self.schema)

        schema = compute_schema(self.schema,
                                getattr(self, 'get_schema_kwargs', dict()), qs,
                                qs.include)

        result = schema.dump(obj).data

        self.after_get(result)
        return result
Example #16
0
    def get(self, *args, **kwargs):
        """Get object details"""
        self.before_get(args, kwargs)

        qs = QSManager(request.args, self.schema)

        obj = self.get_object(kwargs, qs)

        self.before_marshmallow(args, kwargs)

        schema = compute_schema(self.schema,
                                getattr(self, 'get_schema_kwargs', dict()), qs,
                                qs.include)

        result = schema.dump(obj) if obj else None

        final_result = self.after_get(result)

        return final_result
    def patch(self, *args, **kwargs):
        """Update an object"""
        qs = QSManager(request.args, self.schema)
        schema_kwargs = getattr(self, 'patch_schema_kwargs', dict())

        schema = compute_schema(self.schema, schema_kwargs, qs,
                                qs.include + self.default_include)

        data = self._validate_schema(args, kwargs, schema)
        if isinstance(data, tuple):
            return data

        self.before_patch(args, kwargs, data=data)

        obj = self.update_object(data, qs, kwargs)

        result = schema.dump(obj)

        final_result = self.after_patch(result)

        return final_result
Example #18
0
    def post(self, *args, **kwargs):
        """Create an object
        """
        self.before_post(args, kwargs)

        json_data = request.get_json()

        qs = QSManager(request.args, self.schema)

        schema = compute_schema(self.schema,
                                getattr(self, 'post_schema_kwargs', dict()),
                                qs, qs.include)

        try:
            data, errors = schema.load(json_data)
        except IncorrectTypeError as e:
            errors = e.messages
            for error in errors['errors']:
                error['status'] = '409'
                error['title'] = "Incorrect type"
            return errors, 409
        except ValidationError as e:
            errors = e.messages
            for message in errors['errors']:
                message['status'] = '422'
                message['title'] = "Validation error"
            return errors, 422

        if errors:
            for error in errors['errors']:
                error['status'] = "422"
                error['title'] = "Validation error"
            return errors, 422

        obj = self._data_layer.create_object(data, kwargs)

        result = schema.dump(obj).data
        self.after_post(result)
        return result, 201, {'Location': result['data']['links']['self']}
Example #19
0
    def get(self, *args, **kwargs):
        """Retrieve a collection of objects
        """
        qs = QSManager(request.args, self.schema)

        object_count, objects = self.data_layer.get_collection(qs, **kwargs)

        schema_kwargs = getattr(self.opts, 'schema_get_kwargs', dict())
        schema_kwargs.update({'many': True})

        schema = compute_schema(self.schema,
                                schema_kwargs,
                                qs,
                                qs.include)

        result = schema.dump(objects)

        view_kwargs = request.view_args if getattr(self.opts, 'view_kwargs', None) is True else dict()
        add_pagination_links(result.data,
                             object_count,
                             qs,
                             url_for(self.view, **view_kwargs))

        return result.data
Example #20
0
    def post(self, *args, **kwargs):
        """Create an object
        """
        json_data = request.get_json()

        qs = QSManager(request.args, self.schema)

        schema = compute_schema(self.schema,
                                getattr(self.opts, 'schema_post_kwargs', dict()),
                                qs,
                                qs.include)

        try:
            data, errors = schema.load(json_data)
        except IncorrectTypeError as e:
            errors = e.messages
            for error in errors['errors']:
                error['status'] = '409'
                error['title'] = "Incorrect type"
            return errors, 409
        except ValidationError as e:
            errors = e.messages
            for message in errors['errors']:
                message['status'] = '422'
                message['title'] = "Validation error"
            return errors, 422

        if errors:
            for error in errors['errors']:
                error['status'] = "422"
                error['title'] = "Validation error"
            return errors, 422

        obj = self.data_layer.create_object(data, **kwargs)

        return schema.dump(obj).data, 201