I'm currently developing a Django application which will make use of the infamous "pagination" technique. I'm trying to figure out how the django.core.paginator module works.
I have an application with a Question model. I will be listing all of the questions using this paginator. There will be 20 questions per page.
def show_question(question_pk):
questions = Question.objects.all()
paginator = Paginator(questions, 20)
page = ... # Somehow figure out which page the question is on
return render_to_response('show_question.html', { 'page' : page })
In the view, where I list the different pages as "... 2, 3, 4, 5, 6, ..." I want to highlight the current page somehow, like many pages do.
There are really two things I want to know:
EDIT: Sorry, I forgot part of this question. I would also like any page except for the current one to be a link to /questions/{{ that_page.start_index }}
. So basically every page link would link to the first question on that page.
Django provides a few classes that help you manage paginated data – that is, data that's split across several pages, with “Previous/Next” links. These classes live in django/core/paginator.py. For examples, see the Pagination topic guide.
Hmm... I see from your comment that you don't want to do the ol' GET parameter, which is what django.core.paginator was written for using. To do what you want, I can think of no better way than to precompute the page that each question is on. As an example, your view will end up being something like:
ITEMS_PER_PAGE = 20
def show_question(question_pk):
questions = Question.objects.all()
for index, question in enumerate(questions):
question.page = ((index - 1) / ITEMS_PER_PAGE) + 1
paginator = Paginator(questions, ITEMS_PER_PAGE)
page = paginator.page(questions.get(pk=question_pk).page)
return render_to_response('show_question.html', { 'page' : page })
To highlight the current page in the template, you'd do something like
{% for i in page.paginator.page_range %}
{% ifequal i page.number %}
<!-- Do something special for this page -->
{% else %}
<!-- All the other pages -->
{% endifequal %}
{% endfor %}
As for the items, you'll have two different object_lists to work with...
page.object_list
will be the objects in the current page and
page.paginator.object_list
will be all objects, regardless of page. Each of those items will have a "page" variable that will tell you which page they're on.
That all said, what you're doing sounds unconventional. You may want to rethink, but either way, good luck.
Django, at least from version 1.2, allows us to complete this task by using pure default pagination template tags.
{% for page in article_list.paginator.page_range %}
{% if page == article_list.number %}
{{ page }}
{% else %}
<a href="/page{{ page }}">{{ page }}</a>
{% endif %}
{% endfor %}
Where article_list is instance of
paginator = Paginator(article_list, 20)
try:
article_list = paginator.page(int(page))
except (EmptyPage, InvalidPage):
article_list = paginator.page(paginator.num_pages)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With