Reputation: 2067
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
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
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
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