def decode_cursor(self, request): """ Given a request with a cursor, return a `Cursor` instance. Differs from the standard CursorPagination to handle a tuple in the position field. """ # Determine if we have a cursor, and if so then decode it. encoded = request.query_params.get(self.cursor_query_param) if encoded is None: return None try: querystring = b64decode(encoded.encode('ascii')).decode('ascii') tokens = parse.parse_qs(querystring, keep_blank_values=True) offset = tokens.get('o', ['0'])[0] offset = _positive_int(offset, cutoff=self.offset_cutoff) reverse = tokens.get('r', ['0'])[0] reverse = bool(int(reverse)) # The difference. Don't get just the 0th entry: get all entries. position = tokens.get('p', None) except (TypeError, ValueError): raise NotFound(self.invalid_cursor_message) return Cursor(offset=offset, reverse=reverse, position=position)
def decode_cursor(self, request): """ Given a request with a cursor, return a `Cursor` instance. """ # Determine if we have a cursor, and if so then decode it. encoded = request.query_params.get(self.cursor_query_param) if encoded is None: return None # The offset in the cursor is used in situations where we have a # nearly-unique index. (Eg millisecond precision creation timestamps) # We guard against malicious users attempting to cause expensive database # queries, by having a hard cap on the maximum possible size of the offset. OFFSET_CUTOFF = getattr(settings, 'CURSOR_PAGINATION_OFFSET_CUTOFF', 1000) try: querystring = b64decode(encoded.encode('ascii')).decode('ascii') tokens = parse_qs(querystring, keep_blank_values=True) offset = tokens.get('o', ['0'])[0] offset = _positive_int(offset, cutoff=OFFSET_CUTOFF) reverse = tokens.get('r', ['0'])[0] reverse = bool(int(reverse)) position = tokens.get('p', [None])[0] except (TypeError, ValueError): raise NotFound(self.invalid_cursor_message) return Cursor(offset=offset, reverse=reverse, position=position)
def decode_cursor(self, request): """ Given a request with a cursor, return a `Cursor` instance. """ # Determine if we have a cursor, and if so then decode it. encoded = request.query_params.get(self.cursor_query_param) if encoded is None: return None try: reverse = False if encoded.startswith('-'): encoded = encoded[1:] reverse = True offset = 0 parts = encoded.split('+', 1) if '-' in parts[0]: position = parts[0] else: position = None if len(parts) > 1: offset = _positive_int(parts[1], cutoff=self.offset_cutoff) except (TypeError, ValueError): raise NotFound(self.invalid_cursor_message) return Cursor(offset=offset, reverse=reverse, position=position)
def get_next_link(self): if not self.has_next: return None offset = self.page_size if not self.has_previous else self.cursor.offset + self.page_size cursor = Cursor(offset=offset, reverse=False, position=None) return self.encode_cursor(cursor)
def get_previous_link(self): if not self.has_previous: return None offset = self.cursor.offset - self.page_size if offset < 0: offset = 0 cursor = Cursor(offset=offset, reverse=False, position=None) return self.encode_cursor(cursor)
def decode_cursor(self, request): bucket = self._context.get('bucket') key_marker = self.get_key_marker(request) position = None if key_marker: try: upload = MultipartUploadManager().get_multipart_upload_delete_invalid(bucket=bucket, obj_path=key_marker) except exceptions.S3Error as e: raise e if upload: position = upload.create_time else: upload_id_marker = self.get_upload_id_marker(request) if upload_id_marker: position = get_datetime_from_upload_id(upload_id_marker) else: raise exceptions.S3NoSuchUpload('key-marker upload not found.') return Cursor(offset=0, reverse=False, position=position)
def _get_start_after_cursor(self, start_after): """ 获取分页起始参数start_after对应的游标cursor :param start_after: 对象Key :return: Cursor() or None :raises: S3Error """ hm = HarborManager() bucket = self._context.get('bucket', None) if not bucket: bucket_name = self._context('bucket_name') bucket = hm.get_bucket(bucket_name=bucket_name) if not bucket: return None table_name = bucket.get_bucket_table_name() try: obj = HarborManager().get_metadata_obj(table_name=table_name, path=start_after) except exceptions.S3Error as e: raise e if not obj: raise exceptions.S3NoSuchKey(_('无效的参数start_after')) order = self.ordering[0] is_reversed = order.startswith('-') attr = obj.id # order by id if is_reversed: # 倒序 position = max(attr - 1, 0) reverse = False else: position = attr + 1 reverse = True return Cursor(offset=0, reverse=reverse, position=position)
def decode_cursor(self, request): key_marker = self.get_key_marker(request) position = key_marker if key_marker else None return Cursor(offset=0, reverse=False, position=position)