class ModelView(BaseView): def __init__(self): cls = self.__class__ self.controller = ensure_instance(cls.controller) self.serializer = ensure_instance(cls.serializer) self.filter_chain = [ensure_instance(f) for f in cls.filter_chain] self.endpoint_prefix = cls.endpoint_prefix if hasattr(cls, 'endpoint_prefix') else underscore(pluralize(self.controller.model.__name__)) self.dashed_endpoint = dasherize(self.endpoint_prefix) self.query_filter = UnderscoreFilter() def filter(self, subject): def apply_filter_chain(m): dct = self.serializer.serialize(m) for filter in self.filter_chain: dct = filter.filter(dct, g.ctx) return dct if isinstance(subject, BaseModel): return apply_filter_chain(subject) elif isinstance(subject, Iterable): return list(imap(apply_filter_chain, subject)) else: raise TypeError('Filters expect the objects to be of type BaseModel') def make_view(self, api, func): @wraps(func) def wrapper(*args, **kwargs): data, code = func(*args, **kwargs) data = self.filter(data) return api.make_response(data, code) return wrapper @route('/{dashed_endpoint}/') def index(self): return self.controller.index(g.ctx), 200 @route('/{dashed_endpoint}/<int:id>') def get(self, id): return self.controller.read(id, g.ctx), 200 @route('/{dashed_endpoint}/') def post(self): return self.controller.create(g.ctx.input, g.ctx), 201 @route('/{dashed_endpoint}/<int:id>') def put(self, id): return self.controller.update(id, g.ctx.input, g.ctx), 200 @route('/{dashed_endpoint}/<int:id>') def patch(self, id): return self.controller.update(id, g.ctx.input, g.ctx), 200 @route('/{dashed_endpoint}/<int:id>') def delete(self, id): return self.controller.delete(id, g.ctx), 200 @route('/{dashed_endpoint}/query') def query(self): query = self.query_filter.filter(request.args.to_dict()) for k, v in query.items(): if v == '' or v == 'null': query[k] = None return self.controller.query(query, g.ctx), 200