yierstem
yierstem

Reputation: 2067

Django Pagination from ?page= to /page/

I have this view:

class PageView(ListView):
    # ... code ...
    paginate_by = 4

In template I have something like:

<div class="pagination">
          <span class="page-links">
              {% if page_obj.has_previous %}
                  <a href="{{ request.path }}?page={{ page_obj.previous_page_number }}">previous</a>
              {% endif %}
              <span class="page-current">
                  Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
              </span>
              {% if page_obj.has_next %}
                  <a href="{{ request.path }}?page={{ page_obj.next_page_number }}">next</a>
              {% endif %}
          </span>
        </div>

How can I transform GET variable ?page=number to look like /page/number/ in django?

Upvotes: 5

Views: 2734

Answers (3)

yierstem
yierstem

Reputation: 2067

OK. I solved it. Actually when I had:

url(r'^events/(?P<page>[0-9]+)/$', views.PageView.as_view(), name='events'),

It raises an error because page argument is missing and urls.py doesn't know /events/ path.

So, in my url mapping (urls.py) I've written:

url(r'^events/$', views.PageView.as_view(), name='events'),
url(r'^events/(?P<page>[a-z0-9]+)/$', views.PageView.as_view(), name='events'),

When I go to /events/, no arguments needed, page is set to 1 because no page_kwarg is provided, all good.

When I go to /events/<page>/, takes that variable and finally it's working.

Edit: I put [a-z0-9] instead of [0-9] because it's needed when you access /events/last/. In url template tag I must provide last as a string: {% url 'events' 'last' %}

Thanks for answers, If you think my solution is not good, please comment below my answer.

Sorry for my grammar.

Upvotes: 0

Kos
Kos

Reputation: 72221

I cannot test it now but you should be able to re-use all of ListView.

Have a look at django.views.generic.list.MultipleObjectMixin#paginate_queryset:

def paginate_queryset(self, queryset, page_size):
    """
    Paginate the queryset, if needed.
    """
    paginator = self.get_paginator(
        queryset, page_size, orphans=self.get_paginate_orphans(),
        allow_empty_first_page=self.get_allow_empty())
    page_kwarg = self.page_kwarg

    # HERE
    page = self.kwargs.get(page_kwarg) or self.request.GET.get(page_kwarg) or 1

    try:
        page_number = int(page)
    except ValueError:
        if page == 'last':
            page_number = paginator.num_pages
        else:
            raise Http404(_("Page is not 'last', nor can it be converted to an int."))
    try:
        page = paginator.page(page_number)
        return (paginator, page, page.object_list, page.has_other_pages())
    except InvalidPage as e:
        raise Http404(_('Invalid page (%(page_number)s): %(message)s') % {
            'page_number': page_number,
            'message': str(e)
        })

This means that Django looks for the page number first in the view's kwargs, and then in the get parameters.

The values in self.kwargs come from the view's own **kwargs - see django.views.generic.base.View#as_view. This means you should be able to just define a URL like url(r'^event/(?P<page>'d+)/$' and use it with your existing CBV - it should pick up the page number on its own.

Upvotes: 3

devalone
devalone

Reputation: 585

for example, you can use view function:

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

def listOfSomethinView(request, page):
    paginator(Something.objects.all(), 10)
    try:
        list_of_something = paginator.page(page)
    except PageNotAnInteger:
        list_of_something = paginator.page(1)
    except EmptyPage:
        list_of_something = paginator.page(paginator.num_pages)

    return render(request, 'path_to_your_template', {
        'list_of_something': list_of_something,
    })

in urls.py add this:

url(r'^event/(?P<page>[0-9]{1,10})/$', views.listOfSomethingView, name='listOfSomething')

in your template use something like this

{% url 'app:listOfSomething' paginator.previous_page_number %}

Upvotes: 1

Related Questions