def get_paginated_data(request, results, page_num, per_page): """ Return a dict with the following values: next: The URL for the next page previous: The URL for the previous page results: The results on this page """ # Note: Previous versions of this function used Django Rest Framework's # paginated serializer. With the upgrade to DRF 3.1, paginated serializers # have been removed. We *could* use DRF's paginator classes, but there are # some slight differences between how DRF does pagination and how we're doing # pagination here. (For example, we respond with a next_url param even if # there is only one result on the current page.) To maintain backwards # compatability, we simulate the behavior that DRF used to provide. page = _Page(results, page_num, per_page) next_url, previous_url = None, None base_url = request.build_absolute_uri() if page.has_next(): next_url = replace_query_param(base_url, "page", page.next_page_number()) if page.has_previous(): previous_url = replace_query_param(base_url, "page", page.previous_page_number()) return { "next": next_url, "previous": previous_url, "results": results, }
def get_paginated_response(self, data): self_link = self.request.build_absolute_uri() if self_link.endswith(".api"): self_link = self_link[:-4] if self.page.has_next(): next_link = replace_query_param( self_link, self.page_query_param, self.page.next_page_number()) else: next_link = None if self.page.has_previous(): prev_link = replace_query_param( self_link, self.page_query_param, self.page.previous_page_number()) else: prev_link = None return response.Response(OrderedDict([ ('_links', OrderedDict([ ('self', dict(href=self_link)), ('next', dict(href=next_link)), ('previous', dict(href=prev_link)), ])), ('count', self.page.paginator.count), ('_embedded', data) ]))
def test_valid_unicode_replaced(self): q = '/?page=1' value = '1' new_key = 'q' new_value = '%E6%9F%A5%E8%AF%A2' assert new_key in replace_query_param(q, new_key, new_value) assert value in replace_query_param(q, new_key, new_value)
def test_valid_unicode_preserved(self): q = '/?q=%E6%9F%A5%E8%AF%A2' new_key = 'page' new_value = 2 value = '%E6%9F%A5%E8%AF%A2' assert new_key in replace_query_param(q, new_key, new_value) assert value in replace_query_param(q, new_key, new_value)
def get_previous_link(self): if self.page == 1: return None url = self.request.build_absolute_uri() url = replace_query_param(url, self.page_size_query_param, self.limit) url = replace_query_param(url, self.page_query_param, self.page - 1) return url
def get_next_link(self): if not self.has_next_page: return None url = self.request.build_absolute_uri() url = replace_query_param(url, self.page_size_query_param, self.limit) url = replace_query_param(url, self.page_query_param, self.page + 1) return url
def get_next_link(self): if self.offset + self.limit >= self.count: return None url = self.request.build_absolute_uri() url = replace_query_param(url, self.limit_query_param, self.limit) offset = self.offset + self.limit return replace_query_param(url, self.offset_query_param, offset)
def get_next_link(self, data=[]): if len(data) < self.limit: return None url = self.request.build_absolute_uri() url = replace_query_param(url, self.limit_query_param, self.limit) offset = data[-1]['ranking'] return replace_query_param(url, self.offset_query_param, offset)
def get_previous_link(self): if self.offset <= 0: return None url = self.request.build_absolute_uri() url = replace_query_param(url, self.limit_query_param, self.limit) if self.offset - self.limit <= 0: return remove_query_param(url, self.offset_query_param) offset = self.offset - self.limit return replace_query_param(url, self.offset_query_param, offset)
def get_last_link(self): if self.count == 0: return None url = self.request.build_absolute_uri() url = replace_query_param(url, self.limit_query_param, self.limit) offset = self.count - self.limit if offset <= 0: return remove_query_param(url, self.offset_query_param) return replace_query_param(url, self.offset_query_param, offset)
def add_query_param(request, key, val): """ Add a query parameter to the current request url, and return the new url. """ iri = request.get_full_path() uri = iri_to_uri(iri) return escape(replace_query_param(uri, key, val))
def get_last_link(self): url = self.request.build_absolute_uri() page_number = self.paginator.num_pages # only add a 'last' link if it isn't going to be the same as the 'first' link. if page_number != 1: return replace_query_param(url, self.page_query_param, page_number)
def test_invalid_unicode(self): # Encoded string: '��<script>alert(313)</script>=1' q = '/e/?%FF%FE%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%28%33%31%33%29%3C%2F%73%63%72%69%70%74%3E=1' key = 'from' value = 'login' assert key in replace_query_param(q, key, value)
def get_first_link(self, display_page_query_param=True): url = self.request.build_absolute_uri() if display_page_query_param: page_number = self.page.paginator.validate_number(1) return replace_query_param(url, self.page_query_param, page_number) else: return remove_query_param(url, self.page_query_param)
def get_previous_link(self): if not self.page.has_previous(): return None url = self.request.build_absolute_uri() page_number = self.page.previous_page_number() if page_number == 1: return remove_query_param(url, self.page_query_param) return replace_query_param(url, self.page_query_param, page_number)
def adjust_offset(self, url, page_offset): if url is None: return (scheme, netloc, path, query, fragment) = urlparse.urlsplit(force_str(url)) query_dict = QueryDict(query) try: offset = pagination._positive_int( query_dict[self.offset_query_param], ) except (KeyError, ValueError): pass else: if offset > page_offset: url = replace_query_param(url, self.offset_query_param, max(0, offset - self.overlapping)) elif offset < page_offset: url = replace_query_param(url, self.offset_query_param, offset + self.overlapping) return url
def get_next_link(self): """ Returns absolute url of the next page if there's a next page available otherwise returns None """ next_url = None if self.page.has_next(): next_url = replace_query_param(self.base_url, "page", self.page.next_page_number()) return next_url
def get_previous_link(self): """ Returns absolute url of the previous page if there's a previous page available otherwise returns None """ previous_url = None if self.page.has_previous(): previous_url = replace_query_param(self.base_url, "page", self.page.previous_page_number()) return previous_url
def test_valid_offset_limit(self): """ Basic test, assumes offset and limit are given. """ offset = 10 limit = 5 count = len(self.queryset) last_offset = (count // limit) * limit next_offset = 15 prev_offset = 5 request = self.get_test_request({ self.pagination.limit_query_param: limit, self.pagination.offset_query_param: offset }) base_url = replace_query_param(self.base_url, self.pagination.limit_query_param, limit) last_url = replace_query_param(base_url, self.pagination.offset_query_param, last_offset) first_url = base_url next_url = replace_query_param(base_url, self.pagination.offset_query_param, next_offset) prev_url = replace_query_param(base_url, self.pagination.offset_query_param, prev_offset) queryset = self.paginate_queryset(request) content = self.get_paginated_content(queryset) next_offset = offset + limit expected_content = { 'results': list(range(offset + 1, next_offset + 1)), 'links': OrderedDict([ ('first', first_url), ('last', last_url), ('next', next_url), ('prev', prev_url), ]), 'meta': { 'pagination': OrderedDict([ ('count', count), ('limit', limit), ('offset', offset), ]) } } assert queryset == list(range(offset + 1, next_offset + 1)) assert content == expected_content
def page_number_query(self, url, page_number): """ Builds uri and adds page param. """ url = remove_query_param(self.request.build_absolute_uri(url), '_') paginated_url = replace_query_param(url, self.page_query_param, page_number) if page_number == 1: return remove_query_param(paginated_url, self.page_query_param) return paginated_url
def get_last_link(self): """ Return the URL of the last paginated page """ if not self.get_next_link(): return None return replace_query_param( self.request.build_absolute_uri(), self.offset_query_param, self.count - self.limit, )
def pagination(self): pages = {} for pnum in range(self.paginator.num_pages): url = self.paginator.request.build_absolute_uri() pg_url = replace_query_param(url, 'page', pnum + 1) pages[pnum + 1] = pg_url return OrderedDict([ ('next', self.next_url), ('previous', self.previous_url), ('current_page', self.number), ('num_pages', self.paginator.num_pages), ('pages', pages) ])
def encode_cursor(self, cursor): """ Given a Cursor instance, return an url with encoded cursor. """ tokens = {} if cursor.offset != 0: tokens['o'] = str(cursor.offset) if cursor.reverse: tokens['r'] = '1' if cursor.position is not None: tokens['p'] = cursor.position querystring = urlparse.urlencode(tokens, doseq=True) encoded = b64encode(querystring.encode('ascii')).decode('ascii') return replace_query_param(self.base_url, self.cursor_query_param, encoded)
def get_previous_link(self): if not self.has_previous: return None if self.cursor and not self.cursor.reverse and self.cursor.offset != 0: # If we're reversing direction and we have an offset cursor # then we cannot use the first position we find as a marker. compare = self._get_position_from_instance(self.page[0], self.ordering) else: compare = self.previous_position offset = 0 for item in self.page: position = self._get_position_from_instance(item, self.ordering) if position != compare: # The item in this position and the item following it # have different positions. We can use this position as # our marker. break # The item in this postion has the same position as the item # following it, we can't use it as a marker position, so increment # the offset and keep seeking to the previous item. compare = position offset += 1 else: # There were no unique positions in the page. if not self.has_next: # We are on the final page. # Our cursor will have an offset equal to the page size, # but no position to filter against yet. offset = self.page_size position = None elif self.cursor.reverse: # Use the position from the existing cursor and increment # it's offset by the page size. offset = self.cursor.offset + self.page_size position = self.next_position else: # The change in direction will introduce a paging artifact, # where we end up skipping back a few extra items. offset = 0 position = self.next_position cursor = Cursor(offset=offset, reverse=True, position=position) encoded = _encode_cursor(cursor) return replace_query_param(self.base_url, self.cursor_query_param, encoded)
def get_paginated_response(self, data): base_url = self.request.build_absolute_uri() url = base_url[:base_url.find("?")] pages = dict((i, replace_query_param(base_url, 'page', i)) for i in range(1, self.page.paginator.num_pages + 1)) return Response(OrderedDict([ ('results', data), ('count', self.page.paginator.count), ('url', url), ('pagination', { 'current_page': self.page.number, 'next': self.get_next_link(), 'previous': self.get_previous_link(), 'num_pages': self.page.paginator.num_pages, 'pages': pages }) ]))
def _get_paginate_link(self, page_number) -> str: """ Args: page_number: int Returns: string: URL of the requested page """ try: self.pagination.validate_number(page_number) except EmptyPage: return '' url = self.request.build_absolute_uri() if page_number == 1: return remove_query_param(url, 'page') return replace_query_param(url, 'page', page_number)
def preserve_builtin_query_params(url, request=None): """ Given an incoming request, and an outgoing URL representation, append the value of any built-in query parameters. """ if request is None: return url overrides = [ api_settings.URL_FORMAT_OVERRIDE, ] for param in overrides: if param and (param in request.GET): value = request.GET[param] url = replace_query_param(url, param, value) return url
def get_all_links(self): paginator = self.page.paginator links = [] base_url = self.request.build_absolute_uri() for page_number in paginator.page_range: s_link = "" if page_number == 1: s_link = remove_query_param( base_url, self.page_query_param ) else: s_link = replace_query_param( base_url, self.page_query_param, page_number ) links.append({ 'page': page_number, 'url': s_link }) return links
def get_self_link(self): url = self.request.build_absolute_uri() page_number = self.page.number return replace_query_param(url, self.page_query_param, page_number)
def page_number_to_url(page_number): if page_number == 1: return remove_query_param(base_url, self.page_query_param) else: return replace_query_param(base_url, self.page_query_param, page_number)
def get_last_link(self): url = self.request.get_full_path() url = replace_query_param(url, self.limit_query_param, self.limit) offset = self.count - self.limit if (self.count - self.limit) >= 0 else 0 return replace_query_param(url, self.offset_query_param, offset)
def page_number_to_url(page_number): if page_number == 1: return remove_query_param(base_url, self.page_query_param) else: return replace_query_param(base_url, self.page_query_param, page_number)
def get_next_link(self): url = self.get_base_url() url = replace_query_param(url, self.limit_query_param, self.limit) offset = self.offset + self.limit return replace_query_param(url, self.offset_query_param, offset)
def get_last_link(self): total_count = self.page.paginator.count per_page_count = self.get_page_size(self.request) total_pages = int(math.ceil(float(total_count) / per_page_count)) url = self.request.build_absolute_uri() return replace_query_param(url, self.page_query_param, total_pages)
def get_tasks(self, obj): request = self.context["request"] url = request.build_absolute_uri(reverse("tasks-list")) return replace_query_param(url=url, key="group", val=obj.pk)
def page_number_to_url(page_number): if page_number == 1: return remove_query_param(base_url, self.offset_query_param) else: offset = self.offset + ((page_number - current) * self.limit) return replace_query_param(base_url, self.offset_query_param, offset)
def _get_first_link(self): url = self.request.build_absolute_uri() return replace_query_param(url, self.page_query_param, 1)
def get_current_link(self): url = self.request.build_absolute_uri() url = replace_query_param(url, self.page_size_query_param, self.limit) url = replace_query_param(url, self.page_query_param, self.page) return url
def get_first_url(self): if not self.page.has_previous(): return None url = self.request.build_absolute_uri() return replace_query_param(url, self.page_query_param, 1)
def get_last_url(self): if not self.page.has_next(): return None url = self.request.build_absolute_uri() return replace_query_param(url, self.page_query_param, self.page.paginator.num_pages)
def get_first_link(self): url = self.request.get_full_path() url = replace_query_param(url, self.limit_query_param, self.limit) return replace_query_param(url, self.offset_query_param, 0)
def get_next_link(self): url = self.request.build_absolute_uri() page_number = int(self.request.GET.get('page', 1)) + 1 return replace_query_param(url, self.page_query_param, page_number)
def get_next_link(self) -> Optional[str]: if not self.has_next(): return None url = self.url page_number = self.page + 1 return replace_query_param(url, self.page_number_param, page_number)
def get_next_link(self): if not self.page.has_next(): return None url = self.request.get_full_path() page_number = self.page.next_page_number() return replace_query_param(url, self.page_query_param, page_number)
def get_next_link(request, page, per_page, total): if page * per_page >= total: return None url = request.build_absolute_uri() return replace_query_param(url, "page", page + 1)
def _get_previous_link(self): url = self.request.build_absolute_uri() if self.page_num == 1: return remove_query_param(url, self.page_query_param) return replace_query_param(url, self.page_query_param, self.page_num - 1)
def _has_page(has_page, page, request): base_url = replace_query_param(request.build_absolute_uri(), 'page', page) return None if has_page is False else base_url
def get_previous_link(self, data): url = self.request.build_absolute_uri() page_seek_id = data[0]['id'] + self.page_size return replace_query_param(url, self.page_query_param, page_seek_id)
def get_next_link(self): if not self.page.has_next(): return None url = self.request.build_absolute_uri() page_number = self.page.next_page_number() return replace_query_param(url, self.page_query_param, page_number)
def get_previous_link(self): url = self.request.build_absolute_uri() url = replace_query_param(url, 'scope', self.scope) return replace_query_param(url, 'for_date', self.get_previous_date())
def build_link(self, index): if not index: return None url = self.request and self.request.build_absolute_uri() or '' return replace_query_param(url, self.page_query_param, index)
def get_page_link(self, page: typing.Any = 1) -> typing.Optional[str]: if page: return replace_query_param(self.base_url, self.page_query_param, page)
def _get_next_link(self): url = self.request.build_absolute_uri() if self.page_num == len(self.paged_list): return '' return replace_query_param(url, self.page_query_param, self.page_num + 1)
def get_page_link_tmpl(self) -> str: url_tmpl = self.request.build_absolute_uri() url_tmpl = replace_query_param(url_tmpl, self.page_size_query_param, self.per_page) return url_tmpl
def get_paginator(self): url = self.request.build_absolute_uri() page_number = self.page.paginator.num_pages return replace_query_param(url, self.page_query_param, page_number)
def get_previous_link(request, page, current_page): if current_page == 1: return None url = request.build_absolute_uri() return replace_query_param(url, "page", page - 1)
def page_number_to_url(page_number): if page_number == 1: return remove_query_param(base_url, self.offset_query_param) else: offset = self.offset + ((page_number - current) * self.limit) return replace_query_param(base_url, self.offset_query_param, offset)
def get_previous_link(self): url = self.request.build_absolute_uri() page_number = self.page_number - 1 if page_number == 1: return remove_query_param(url, self.page_query_param) return replace_query_param(url, self.page_query_param, page_number)
def get_next_link(self, data): url = self.request.build_absolute_uri() page_seek_id = data[-1]['id'] - 1 return replace_query_param(url, self.page_query_param, page_seek_id)
def _get_last_link(self): url = self.request.build_absolute_uri() page_number = len(self.paged_list) return replace_query_param(url, self.page_query_param, page_number)