[Fixed]-Django pagination and "current page"

13đź‘Ť

âś…

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.

👤uzi

11đź‘Ť

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)

5đź‘Ť

django-pagination should do what you want and comes wrapped in a pretty package you can just plug-in and use. It essentially moves the code from your views to the templates and a middleware.

EDIT: I just saw your edit.
You can get the current objects on a page using {% autopaginate object_list %}, which replaces object_list with the current objects for any given page. You can iterate through it and if you want the first, you should be able to treat it like a list and do object_list[0].

If you want to keep this within your views, you could do something like this:

def show_question(question_pk):
    questions = Question.objects.all()
    paginator = Paginator(questions, 20)
    return render_to_response('show_question.html', { 'page' : paginator })

Within your template, you can access the current page you’re on by doing:

# Gives you the starting index for that page.
# For example, 5 objects, and you're on the second page. 
# start_index will be 3.
page.start_index

# You can access the current page number with:
# 1-based index
page.number

With that, you should be able to do everything you need.
There are a couple good examples here.

👤Nick Presta

Leave a comment