Django's built-in paginator works in terms of fixed-size pages. While usable in API context, this might pose problems if results are likely to change between subsequent page requests (eg. more data pours in).
A simple pagination model with since (all objects after the selected one) and limit works better in this case. Here's a sample implementation:
def get_paginated_data(data, start, count, order='-id'):
if order.startswith('-'):
asc = False
order_field = order[1:]
else:
asc = True
order_field = order
ordered_data = data.order_by(order)
if start:
filter_fields = {
order_field + ('__gte' if asc else '__lte'): start
}
ordered_data = ordered_data.filter(**filter_fields)
retval = list(ordered_data[:count + 1])
if len(retval) > count:
obj = retval[count]
while '__' in order_field:
prefix, order_field = order_field.split('__', 1)
obj = getattr(obj, prefix)
next = getattr(obj, order_field)
retval = retval[:-1]
else:
next = None
return (retval, next)
Note that this example includes the "since" object in results (in effect, returning it twice).
Django's built-in paginator works in terms of fixed-size pages. While usable in API context, this might pose problems if results are likely to change between subsequent page requests (eg. more data pours in).
A simple pagination model with
since(all objects after the selected one) andlimitworks better in this case. Here's a sample implementation:Note that this example includes the "since" object in results (in effect, returning it twice).