Source code for flump.methods.post

from flask import jsonify
from werkzeug.exceptions import Forbidden

from ..exceptions import FlumpUnprocessableEntity
from ..schemas import ResponseData, make_data_schema, make_entity_schema
from ..web_utils import get_json, url_for
from .defs import HttpMethods


class Post(object):
    def post(self, **kwargs):
        """
        Handles HTTP POST requests.

        Creates an entity based on the current schema and request json. The
        view should provide a method for creating the entity using
        :func:`Post.create_entity`

        :param \**kwargs: Any kwargs taken from the url which are used
                          for building the url identifying the new entity.
        """
        incoming_data, errors = self._post_schema().load(self.post_data)
        if errors:
            raise FlumpUnprocessableEntity(errors=errors)

        if incoming_data.id is not None:
            raise Forbidden(
                'You must not specify an id when creating an entity'
            )

        new_model = self.orm_integration.create_entity(
            incoming_data.attributes
        )

        entity_data = self._build_entity_data(new_model)

        links = {}
        self_url = None
        if HttpMethods.GET <= self.HTTP_METHODS:
            self_url = url_for('.{}'.format(self.RESOURCE_NAME), _external=True,
                               entity_id=entity_data.id, _method='GET',
                               **kwargs)
            links = {'self': self_url}

        schema = self.response_schema(strict=True)
        response_data = ResponseData(entity_data, links)
        data, _ = schema.dump(response_data)

        response = jsonify(data)
        if self_url:
            response.headers['Location'] = self_url

        response.set_etag(str(entity_data.meta.etag))
        return response, 201

    @property
    def _post_schema(self):
        """
        A schema describing the format of POST request for jsonapi. Provides
        automatic error checking for the data format.
        """
        return make_entity_schema(self.SCHEMA, self.RESOURCE_NAME,
                                  make_data_schema(self.SCHEMA))

    @property
    def post_data(self):
        """
        Property so we can override in derived classes to include autogenerated
        attributes such as api_keys.
        """
        return get_json()