def paginate_resource(request, qs, resource_transformer=lambda x: x, on_empty_message=None): """From a request object (an obj that has a dict-like .GET attribute) and a query set, returns a properly paginated query set, together with the info about total pages and current page. Searches the GET query string for a parameter named "page" :param request: a request object :param qs: a queryset (or any - preferably unevaluated - iterable, that supports slicing) :param resource_transformer: a callable, able to transform the queryset model instances into resources (dictionaries usually) :param on_empty_message: the message to be displayed in case there are no elements in the query set. :return: tree structure representing the result """ current_page, page_size = get_page_details_for_request(request) paginator = Paginator(qs, page_size, allow_empty_first_page=False) try: page = paginator.page(current_page) except EmptyPage: if current_page == 1: raise Http404Error(on_empty_message) else: raise Http400Error("Invalid page number. Minimum is 1, maximum is " "{}".format(paginator.num_pages)) objects_on_page = page.object_list result = OrderedDict() result['collection_info'] = serialize_page_metadata( page, request.build_absolute_uri()) result['objects'] = resource_transformer(objects_on_page) result.status_code = 200 return result