Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django pagination and "current page"

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:

  1. How do I make Django figure out which page the question is located at?
  2. How would I write my template to properly "highlight" the currently visited page?

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.

like image 907
Deniz Dogan Avatar asked Apr 14 '09 13:04

Deniz Dogan


People also ask

What is Paginator in Django?

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.


2 Answers

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.

like image 189
uzi Avatar answered Oct 21 '22 07:10

uzi


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)
like image 25
Ivan Kharlamov Avatar answered Oct 21 '22 07:10

Ivan Kharlamov