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}
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)
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
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}
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" } )
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)
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)