示例#1
0
    def validate_create_request(self, req: falcon.Request, is_bulk=False):
        methods = self.Meta.methods
        payload = json.load(req.bounded_stream)

        if isinstance(payload.get(self.Meta.name), list):
            request_method = BULK_CREATE
            is_bulk = True
        else:
            request_method = CREATE

        if request_method not in methods:
            raise MethodNotAllowed()

        data = payload.get(self.Meta.name)

        if not data:
            raise BadRequest(
                f"Invalid schema, resource name is missing at the top level. "
                f"Your POST request has to look like: "
                f'{{"{self.Meta.name}": [{{"field_name": "field_value"}}] '
                f'or {{"field_name": "field_value"}} }}'
            )

        try:
            deserialized = self.load(data, many=is_bulk)
        except ValidationError as exc:
            raise BadRequest(exc.messages)

        req.stream = {self.Meta.name: deserialized}
示例#2
0
    def read__includes(self):
        for i in self.include or []:
            if "." in i:
                raise BadRequest()

            elif not isinstance(self.resource.fields.get(i), (ToOne, ToMany)):
                raise RelationNotFound(f"Relation <{i}> not found")

            related_resource_name = self.resource.fields[i].metadata["resource"]
            related_res = self.resource.RESOURCES[related_resource_name]
            related_field = self.resource.fields[i].metadata.get("model_field")
            method_name = f"get_by_{self.resource.Meta.name.lower()}_ids"

            if not hasattr(related_res, method_name):
                raise BadRequest(
                    f"Relation {related_resource_name} doesn't ready yet. "
                    f"Ask developers to add {method_name} method "
                    f"to {related_resource_name} resource"
                )

            related_res_obj = related_res()
            related_data = getattr(related_res_obj, method_name)(
                self.session, self, related_field
            )
            self.__add_related_payload(related_res, related_data)
示例#3
0
def get_ids_from_payload(model: Any, payload: List[Dict]) -> List:
    if model and hasattr(model, "id"):
        ids = [d.get(model.id.key) for d in payload]
    else:
        raise BadRequest("Model's ID field doesn't specified")

    return ids
示例#4
0
    def validate_update_request(self, req: falcon.Request):
        methods = self.Meta.methods
        if UPDATE not in methods and BULK_UPDATE not in methods:
            raise MethodNotAllowed()

        payload = json.load(req.bounded_stream)
        data = payload.get(self.Meta.name)
        try:
            deserialized = self.load(data, partial=True, many=True)
        except ValidationError as exc:
            raise BadRequest(exc.messages)

        req.stream = {self.Meta.name: deserialized}
示例#5
0
    def check_exists(
        session: Session, table: sa.Table, ids: list, field_name: str
    ):
        result = session.execute(
            sa.select([table.c.id]).where(table.c.id.in_(ids))
        )

        missed = set(ids) - {item.id for item in result}
        if missed:
            raise BadRequest(
                {
                    field_name: f"objects with id {','.join(map(str, missed))} does not exist"
                }
            )
示例#6
0
    def on_delete(
        self,
        req: falcon.Request,
        resp: falcon.Response,
        resource_id: int = None,
    ):
        """
        Falcon method. DELETE-request entry point.

        Here is a database transaction opening.
        This is where authentication takes place
        (if auth class is pointed in `resource <#awokado.meta.ResourceMeta>`_)
        Then delete method is run.
        """

        with Transaction(DATABASE_URL, engine=persistent_engine) as t:
            session = t.session
            user_id, token = self.auth(session, req, resp)

            if DELETE not in self.Meta.methods:
                raise MethodNotAllowed()

            ids_to_delete = req.get_param_as_list("ids")

            data = [ids_to_delete, resource_id]
            if not any(data) or all(data):
                raise BadRequest(
                    details=(
                        "It should be a bulk delete (?ids=1,2,3) or delete"
                        " of a single resource (v1/resource/1)"
                    )
                )

            if not ids_to_delete:
                ids_to_delete = [resource_id]

            if self.Meta.auth:
                self.Meta.auth.can_delete(session, user_id, ids_to_delete)

            result = self.delete(session, user_id, ids_to_delete)

        resp.body = json.dumps(result, default=str)
示例#7
0
    def read_handler(
        self,
        session: Session,
        user_id: int,
        include: list = None,
        filters: Optional[List[FilterItem]] = None,
        sort: list = None,
        resource_id: int = None,
        limit: int = None,
        offset: int = None,
    ) -> dict:

        ctx = ReadContext(
            session,
            self,
            user_id,
            include,
            filters,
            sort,
            resource_id,
            limit,
            offset,
        )

        self.read__query(ctx)
        self.read__filtering(ctx)
        self.read__sorting(ctx)

        self.read__pagination(ctx)
        self.read__execute_query(ctx)

        if not ctx.obj_ids:
            if ctx.is_list:
                response = self.Response(self, is_list=ctx.is_list)
                return response.serialize()
            else:
                raise BadRequest("Object Not Found")

        self.read__includes(ctx)
        return self.read__serializing(ctx)