Skip to content

Instantly share code, notes, and snippets.

@stefanocrosta
Created April 19, 2012 08:17
Show Gist options
  • Save stefanocrosta/2419590 to your computer and use it in GitHub Desktop.
Save stefanocrosta/2419590 to your computer and use it in GitHub Desktop.
Django Paginated Class View
"""
Very simple PaginatedListView
"""
class PaginatedListView(ListView, FormView):
queryset = None
def get_context_data(self, **kwargs):
#logging.debug('ApplicationListView.get_context_data')
context = super(self.__class__, self).get_context_data(**kwargs)
# paginate by
context['is_paginated'] = self.is_paginated
context['page_obj'] = self.page_obj
return context
def get_queryset(self):
## this is where you put your code ##
query_set = CALCULATE YOUR QUERYSET HERE. or use self.query_set
## end of your code ##
# make my own (simple?) pagination
count = query_set.count()
MAX_ELEMENTS = 20
try:
page = int(self.request.GET.get('page', 0))
except:
page = 0
if page or count>MAX_ELEMENTS:
import math
if not page:
page = 1
self.is_paginated = True
_from = (page-1)*MAX_ELEMENTS
_to = min(page*MAX_ELEMENTS-1, count)
last_page = math.trunc(count / MAX_ELEMENTS)+1
query_set = query_set[_from:_to]
query_string = self.request.GET.copy()
query_string['page'] = page+1
next_page_url = query_string.urlencode()
query_string['page'] = page-1
prev_page_url = query_string.urlencode()
self.page_obj = {
'has_previous': page>1,
'has_next': page<last_page,
'number': page,
'next_page_number': page+1,
'next_page': next_page_url,
'prev_page_number': page-1,
'prev_page': prev_page_url,
'paginator': {
'num_pages': last_page
}
}
else:
self.is_paginated = False
self.page_obj = {}
return query_set
@stefanocrosta
Copy link
Author

This is a very simple paginator view with the objective of being very explicit in the database queries so that you can check if you have issues somewere else!

It produces an object compatible with the Django Paginator one.

If your queryset does not change you should use queryset = self.queryset in the ## your code here ## section, and just set the query set as a ClassView property.

If your queryset depends on the request params, get them from self.request.GET|POST|REQUEST|META etc.

@stefanocrosta
Copy link
Author

If you are still writing with the old style views (booo!) you need to:

  1. take the def get_queryset(self): and make it into def get_paginated_queryset(request, queryset):
  2. replace self. with... nothing
  3. return query_set, is_paginated, page_obj` (you can combine the last two)
  4. in your view, after you calculate the query set, do: yourqueryset, is_paginated, page_obj = get_paginated_queryset(request, yourqueryset)
  5. add is_paginated and page_obj to your response context, eg: return render(request, 'myapp/template.html', {"queryset": yourqueryset, "is_paginated": is_paginated, "page_obj": page_obj})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment