pagination.py 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. import math
  2. from django.http import Http404
  3. def make_pagination(page, total, per):
  4. pagination = {'start': 0, 'stop': 0, 'prev':-1, 'next':-1}
  5. page = int(page)
  6. if page == 1:
  7. # This is fugly abuse of "wrong page" handling
  8. # It's done to combat "duplicate content" errors
  9. # If page is 1 instead of 0, that suggests user came
  10. # to page from somewhere/1/ instead of somewhere/
  11. # when this happens We raise 404 to drop /1/ part from url
  12. raise Http404()
  13. if page > 0:
  14. pagination['start'] = (page - 1) * per
  15. # Set page and total stat
  16. pagination['page'] = int(pagination['start'] / per) + 1
  17. pagination['total'] = int(math.ceil(total / float(per)))
  18. # Fix too large offset
  19. if pagination['start'] > total:
  20. pagination['start'] = 0
  21. # Allow prev/next?
  22. if total > per:
  23. if pagination['page'] > 1:
  24. pagination['prev'] = pagination['page'] - 1
  25. if pagination['page'] < pagination['total']:
  26. pagination['next'] = pagination['page'] + 1
  27. # Fix empty pagers
  28. if not pagination['total']:
  29. pagination['total'] = 1
  30. # Set stop offset
  31. pagination['stop'] = pagination['start'] + per
  32. # Put 1/5 of last page on current page...
  33. if pagination['page'] + 1 == pagination['total']:
  34. last_page = per + total - (pagination['total'] * per)
  35. cutoff = int(per / 5)
  36. if cutoff > 1 and last_page < cutoff:
  37. pagination['stop'] += last_page
  38. pagination['total'] -= 1
  39. pagination['next'] = -1
  40. # Raise 404 if page is out of range
  41. if pagination['page'] > pagination['total']:
  42. raise Http404()
  43. # Return complete pager
  44. return pagination
  45. def page_number(item, total, per):
  46. page_item = int(math.ceil(item / float(per)))
  47. pages_total = int(math.ceil(total / float(per)))
  48. last_page = total - ((pages_total - 1) * per)
  49. cutoff = int(per / 5)
  50. if cutoff > 1 and cutoff > last_page and pages_total == page_item and pages_total > 1:
  51. page_item -= 1
  52. return page_item