Django - Pagination display - django

I am having an issue figuring out my pagination for django. Following the docs everything works correctly if I am on the first page or the last page, but I have code duplicating. Everything I have tried I end up getting some sort of exception, mostly empty page exception. I understand that this is because my solutions involve not checking if page_obj.has_previous or .has_next. I am not sure how to solve this and any help would be greatly appreciated. I will attach a screen shot so you can see what I mean.
pagination:
<div class="pagination justify-content-center pt-3">
<nav aria-label='pagination'>
<ul class="pagination step-links">
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}" aria-label='Previous'>
<span aria-hidden='true'>«</span>
</a>
</li>
<li class="page-item">
<a class='page-link'>
{{ page_obj.number }} of {{ page_obj.paginator.num_pages }}
</a>
</li>
{% endif %}
{% if page_obj.has_next %}
<li class="page-item">
<a class='page-link'>
{{ page_obj.number }} of {{ page_obj.paginator.num_pages }}
</a>
</li>
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}" aria-label='Next'>
<span aria-hidden='true'> » </span>
</a>
</li>
{% endif %}
</ul>
</nav>
</div>
As you can see the '2 of 3' gets duplicated. I see exactly why it gets duplicated in my code but if I delete one of the list items then the {{ page_obj.number }} of {{ page_obj.paginator.num_pages }} will not be displayed on the first or last page. What would be the best way to solve this? I haven't been able to figure it out on my own

The code (page-item class) just has to be outside the if block. This will work.
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}" aria-label='Previous'>
<span aria-hidden='true'>«</span>
</a>
</li>
{% endif %}
<li class="page-item">
<a class='page-link'>
{{ page_obj.number }} of {{ page_obj.paginator.num_pages }}
</a>
</li>
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}" aria-label='Next'>
<span aria-hidden='true'> » </span>
</a>
</li>
{% endif %}

Related

Django template large data pagination link issue

I am using the django paginator in my template. Its working ok with less data, but not working good when there's large numbers of pages.
Pagination links code is given bellow:
<div class="paginationWrapper mt-3">
{% if match_list.paginator.num_pages > 1 %}
<ul class="pagination">
{% if match_list.has_previous %}
<li>
<a href="?p={{ match_list.previous_page_number }}
{% if request.GET.search %}&search={{ request.GET.search }}
{% endif %}" class="page-link"><i class="fas fa-angle-double-left"></i></a>
</li>
{% endif %}
{% for j in match_list.paginator.page_range %}
{% if match_list.number == j %}
<li class="active"><a class="page-link" href="#">{{ j }}</a></li>
{% else %}
<li><a href="?p={{ j }}{% if request.GET.search %}&search={{ request.GET.search }}
{% endif %}" class="page-link">{{ j }}</a></li>
{% endif %}
{% endfor %}
{% if match_list.has_next %}
<li>
<a href="?p={{ match_list.next_page_number }}
{% if request.GET.search %}&search={{ request.GET.search }}{% endif %}
" class="page-link"><i class="fas fa-angle-double-right"></i></a>
</li>
{% endif %}
</ul>
{% endif %}
</div>
After this i am gettin the links in my template like :
what i actually want is i want to display only 10 links after that ... to show more can anyone please help me relatred this i am stuck here
https://docs.djangoproject.com/en/3.1/topics/pagination/#paginating-a-listview
try this
{% load core %} // core here is template tag
{% if match_list.paginator.num_pages > 1 %}
<ul class="pagination justify-content-center">
{% if match_list.has_previous %}
<li class="page-item">
<a class="page-link" href="?{% param_replace page=1 %}">
First
</a>
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link" href="#">
First
</a>
</li>
{% endif %}
{% if match_list.has_previous %}
<li class="page-item">
<a class="page-link" href="?{% param_replace page=match_list.previous_page_number %}">
«
</a>
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link" href="#">
«
</a>
</li>
{% endif %}
{% for i in match_list.paginator.page_range %}
{% if match_list.number == i %}
<li class="page-item active">
<a class="page-link" href="#">{{ i }} <span class="sr-only">(current)</span>
</a>
</li>
{% elif match_list.number > i|add:"-5" and match_list.number < i|add:"+5"%}
<li class="page-item"><a class="page-link" href="?{% param_replace page=i %}">{{ i }}</a></li>
{% endif %}
{% endfor %}
{% if match_list.has_next %}
<li class="page-item">
<a class="page-link" href="?{% param_replace page=match_list.next_page_number %}">
»
</a>
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link" href="#">
»
</a>
</li>
{% endif %}
{% if match_list.paginator.num_pages != match_list.number %}
<li class="page-item">
<a class="page-link" href="?{% param_replace page=match_list.paginator.num_pages %}">
Last
</a>
</li>
{% else %}
<li class="page-item disabled"><a class="page-link" href="#">Last</a></li>
{% endif %}
</ul>
{% endif %}
custom template tag
#register.simple_tag(takes_context=True)
def param_replace(context, **kwargs):
"""
"""
d = context['request'].GET.copy()
for k, v in kwargs.items():
d[k] = v
for k in [k for k, v in d.items() if not v]:
del d[k]
return d.urlencode()
output

What is wrong with my logic in for loops - django templates

This is my home.html, problem is with the if block:
{% for menu in menus %}
<div class="dropdown show">
<a class="btn dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{ menu.main_menu_item }}
</a>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuLink">
{% for item in menu.items.all %}
{% for second_item in item.items_second_level.all %}
{% if item.items_second_level.all != None %}
<li class="dropdown-submenu"><a class="dropdown-item dropdown-toggle" href="#">{{ item.sub_menu_item }}</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">{{second_item.sub_menu_item}}</a></li>
</ul>
</li>
{% else %}
<li><a class="dropdown-item" href="#">{{ item.sub_menu_item }}</a></li>
{% endif %}
{% endfor %}
{% endfor %}
</ul>
</div>
{% endfor %}
Namely, {% else %} part always "blanks". When I change condition to {% if item.items_second_level.all == None %}
again, only items which satisfies the if condition get showed (obviously this time the ones that were not shown before). it behaves like there is no else. Does anyone know what could be the issue here?

How to insert the blog pagination on Django Blog

I trying to implement pagination on my blog using the Bootstrap.
I did comment because in this way is working but shows only one number.
I did try some different way but not working yet, I feel that is close. or not. :-)
Following my "blog.html" file.
Thank you.
<nav aria-label="Page navigation example">
<ul class="pagination pagination-lg justify-content-center">
{% if queryset.has_previous %}
<li class="page-item">
<a class="page-link" href="?{{ page_request_var }}={{ queryset.previous_page_number }}" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
{% endif%}
{% comment %} <li class="page-item"><a class="page-link" href="?{{ page_request_var }}">{{ queryset.previous_page_number}}</a></li> {% endcomment %}
<li class="page-item"><a class="page-link" href="?{{ page_request_var }}">{{ queryset.number }}</a></li>
{% comment %} <li class="page-item"><a class="page-link" href="?{{ page_request_var }}">{{ queryset.next_page_number}}</a></li> {% endcomment %}
{% if queryset.has_next %}
<li class="page-item">
<a class="page-link" href="?{{ page_request_var }}={{ queryset.next_page_number }}" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
{% endif%}
</ul>
</nav>
Add pagination in the html file like this:
<ul class="pagination justify-content-center">
{% if is_paginated %}
{% if page_obj.has_previous %}
<a class="btn btn-outline-dark mb-4" href="?page=1">First</a>
<a class="btn btn-outline-dark mb-4" href="?page={{ page_obj.previous_page_number }}">Previous</a>
{% endif %}
{% for num in page_obj.paginator.page_range %}
{% if page_obj.number == num %}
<a class="btn btn-dark mb-4" href="?page={{ num }}">{{ num }}</a>
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
<a class="btn btn-outline-dark mb-4" href="?page={{ num }}">{{ num }}</a>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<a class="btn btn-outline-dark mb-4" href="?page={{ page_obj.next_page_number }}">Next</a>
<a class="btn btn-outline-dark mb-4" href="?page={{ page_obj.paginator.num_pages }}">Last</a>
{% endif %}
{% endif %}
</ul>
I'm supposing you did two things.First you used Paginator in your views.py and also your queryset is not empty. Following code is completely functional and targets your template only:
paginator.html
<div class="pagination-container justify-content-center">
<ul class="pagination pagination-primary">
{% if paginator.has_previous %}
<li class="page-item arrow-margin-left">
<a class="page-link" href="?page={{ paginator.previous_page_number }}" aria-label="Previous">
<span aria-hidden="true"><i class="fa fa-angle-double-left" aria-hidden="true"></i></span>
</a>
</li>
{% else %}
<li class="page-item arrow-margin-left">
<a class="page-link" href="#" aria-label="Previous">
<span aria-hidden="true"><i class="fa fa-angle-double-left" aria-hidden="true"></i></span>
</a>
</li>
{% endif %}
{% for i in paginator.paginator.page_range %}
{% if paginator.number == i %}
<li class="page-item active">
<a class="page-link">{{ i }}</a>
</li>
{% else %}
<li class="page-item">
<a class="page-link" href="?page={{ i }}">
{{ i }}
</a>
</li>
{% endif %}
{% endfor %}
{% if paginator.has_next %}
<li class="page-item arrow-margin-right">
<a class="page-link" href="?page={{ paginator.next_page_number }}" aria-label="Next">
<span aria-hidden="true">
<i class="fa fa-angle-double-right" aria-hidden="true"></i>
</span>
</a>
</li>
{% else %}
<li class="page-item arrow-margin-right">
<a class="page-link" href="#" aria-label="Next">
<span aria-hidden="true">
<i class="fa fa-angle-double-right" aria-hidden="true"></i>
</span>
</a>
</li>
{% endif %}
</ul>
</div>
Now you can call this code wherever you need it, for example :
articles.html
<div class="pagination-container justify-content-center col-md-6">
{% include 'pages/page_articles_paginator.html' with paginator=page_articles%}
</div>
this will assign page_articles to

That page contains no results Django ListView

I have the problem in Django 1.9
I have this problem when I go to the last result pagination
views.py
class UserList(ListView):
model = User
template_name = 'account/users.html'
paginate_by = 1
users.html
<div class="pagination">
<span class="page-links">
{% if page_obj.has_previous %}
previous
{% endif %}
<span class="page-current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
next
{% endif %}
</span>
I've encountered this as well and the problem is that Paginator.page_range is 1-based.
https://docs.djangoproject.com/en/1.9/topics/pagination/#django.core.paginator.Paginator.page_range
I've used the following solution: (I'm using Foundation 6)
{% if is_paginated %}
<ul class="pagination text-center" role="navigation" aria-label="Pagination">
{% if page_obj.has_previous %}
<li class="pagination-previous">
<a href="?page={{ page_obj.previous_page_number }}">
<span>Previous</span>
</a>
</li>
{% else %}
<li class="pagination-previous disabled">
<span>Previous</span>
</li>
{% endif %}
{% for page in paginator.page_range %}
{% if paginator.num_pages != page %}
<li class="{% if page == page_obj.number %}active{% endif %}">
{{ page }}
</li>
{% endif %}
{% endfor %}
{% if page_obj.has_next and paginator.num_pages != page_obj.next_page_number %}
<li class="pagination-next">
<a href="?page={{ page_obj.next_page_number }}">
<span>Next</span>
</a>
</li>
{% else %}
<li class="pagination-next disabled">
<span>Next</span>
</li>
{% endif %}
</ul>
{% endif %}
Hope this helps! I initially based my code from https://ana-balica.github.io/2015/01/29/pagination-in-django/

Django pagination - example from documentation. How to display with all sites number?

This is example from documentation Django:
def listing(request):
contact_list = Contacts.objects.all()
paginator = Paginator(contact_list, 25) # Show 25 contacts per page
page = request.GET.get('page')
try:
contacts = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
contacts = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
contacts = paginator.page(paginator.num_pages)
return render_to_response('list.html', {"contacts": contacts})
template:
{% for contact in contacts %}
{# Each "contact" is a Contact model object. #}
{{ contact.full_name|upper }}<br />
...
{% endfor %}
<div class="pagination">
<span class="step-links">
{% if contacts.has_previous %}
previous
{% endif %}
<span class="current">
Page {{ contacts.number }} of {{ contacts.paginator.num_pages }}.
</span>
{% if contacts.has_next %}
next
{% endif %}
</span>
</div>
This display for example:
Page 2 of 3. next
How to display it in this way:
previous 1 <b>2</b> 3 Next
Current page with html <b> mark.
?
You can try this:
{% for num in contacts.paginator.page_range %}
{% ifequal num contacts.number %}
<span class="current"><b>{{ num }}</b></span>
{% else %}
{{ num }}
{% endifequal %}
{% endfor %}
Below example is actually for class based views but would work fine.
CSS is Twitter Bootstrap V3.0.0.
{% if is_paginated %}
<ul class="pagination">
{% if page_obj.has_previous %}
<li>«</li>
{% else %}
<li class="disabled">«</li>
{% endif %}
{% for num in page_obj.paginator.page_range %}
{% ifequal num page_obj.number %}
<li class="active">{{ num }}<span class="sr-only">(current)</span></li>
{% else %}
<li>{{ num }}</li>
{% endifequal %}
{% endfor %}
{% if page_obj.has_next %}
<li>»</li>
{% else %}
<li class="disabled">»</li>
{% endif %}
</ul>
{% endif %}
This is mine.
{% if page.paginator.num_pages > 1 %}
<nav aria-label="Page navigation">
<ul class="pagination justify-content-center">
{% if page.paginator.num_pages != 1 %}
<li class="page-item"><a class="page-link" href="?page=1">First</a></li>
{% else %}
<li class="page-item disabled"><a class="page-link" href="#">First</a></li>
{% endif %}
{% if page.has_previous %}
<li class="page-item"><a class="page-link" href="?page={{ page.previous_page_number }}">«</a></li>
{% else %}
<li class="page-item disabled"><a class="page-link" href="#">«</a></li>
{% endif %}
{% for i in page.paginator.page_range %}
{% if page.number == i %}
<li class="page-item active"><a class="page-link" href="#">{{ i }} <span class="sr-only">(current)</span></a></li>
{% elif page.number > i|add:"-5" and page.number < i|add:"+5"%}
<li class="page-item"><a class="page-link" href="?page={{ i }}">{{ i }}</a></li>
{% endif %}
{% endfor %}
{% if page.has_next %}
<li class="page-item"><a class="page-link" href="?page={{ page.next_page_number }}">»</a></li>
{% else %}
<li class="page-item disabled"><a class="page-link" href="#">»</a></li>
{% endif %}
{% if page.paginator.num_pages != page.number %}
<li class="page-item"><a class="page-link" href="?page={{ page.paginator.num_pages }}">Last</a></li>
{% else %}
<li class="page-item disabled"><a class="page-link" href="#">Last</a></li>
{% endif %}
</ul>
</nav>
{% endif %}
Looks like
If someone needs Bootstap 4 Alpha 5 version of code.
Also I did two changes:
I do not like duplicates of pages, so I changed in my case /profiles/?page=1 to simple /profiles/.
I have lots of pages, so I do not show all pages. I show just: The 1st, the last, current and +-3 pages from the current one, and every 10th page.
If you need just all pages with Bootstrap 4 without my modifications, just remove unnecessary parts of code (everything is commented).
{% if is_paginated %}
<nav aria-label="Page navigation">
<ul class="pagination">
<!-- << PREVIOUS PART -->
<!-- << Disable 'Previous' page button if you are at the 1st page -->
{% if not page_obj.has_previous %}
<li class="page-item disabled">
<a class="page-link" href="#" tabindex="-1" aria-label="Previous">
<!-- << If you are at the 2nd page,
'Previous' page button will get '/profiles/' url instead of '/profiles/?page=1' -->
{% elif page_obj.previous_page_number == 1 %}
<li class="page-item">
<a class="page-link" href="{{ profiles_1st_page_url }}" aria-label="Previous">
{% else %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}" aria-label="Previous">
{% endif %}
<span aria-hidden="true">«</span>
<span class="sr-only">Previous</span>
</a>
</li>
<!-- PAGES PART -->
{% for num in page_obj.paginator.page_range %}
<!-- Active page -->
{% if num == page_obj.number %}
<li class="page-item active">
<a class="page-link" href="#">{{ num }}<span class="sr-only">(current)</span></a>
</li>
{% else %}
<li class="page-item">
<!-- For the 1st page we do not use ?page=1 -->
{% if num == 1 %}
<a class="page-link" href="{{ profiles_1st_page_url }}">{{ num }}</a>
{% else %}
<!-- Show current page and +-3 pages -->
{% if num|add:"-3" <= page_obj.number and page_obj.number <= num|add:"3" %}
<a class="page-link" href="?page={{ num }}">{{ num }}</a>
<!-- Shows every 10th page and the last page -->
{% elif num|divisibleby:"10" or num == page_obj.paginator.num_pages %}
<a class="page-link" href="?page={{ num }}">{{ num }}</a>
{% endif %}
{% endif %}
</li>
{% endif %}
{% endfor %}
<!-- >> NEXT PART -->
{% if not page_obj.has_next %}
<!-- << Disable 'Next' page button if you are at the last page -->
<li class="page-item disabled">
<a class="page-link" href="#" tabindex="-1" aria-label="Next">
{% else %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}" aria-label="Next">
{% endif %}
<span aria-hidden="true">»</span>
<span class="sr-only">Next</span>
</a>
</li>
</ul>
</nav>
{% endif %}
And it looks like: