How to insert the blog pagination on Django Blog - django

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

Related

Django - Pagination display

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 %}

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

Django - Pagination

I'm working on To-Do App.
I have two kinds of data,
Upcoming To-do Item and
Completed To-do Items.
So, I'm filtering data in views.py as upcoming items and completed items. I want to display them on the same page using pagination. I'm getting result too but if upcoming item completed in page-1 I was unable to visit page-2 because upcoming item for page-2 was empty, but I have items on completed items. I couldn't see that.
views.py
#login_required(login_url='login')
def home(request):
todo_form = TodoForm()
current = timezone.now()
todo_items_upcoming = Todo.objects.filter(user_id=request.user, completed=False).order_by('-date_created')
todo_items_completed = Todo.objects.filter(user_id=request.user, completed=True)
pagi1 = Paginator(todo_items_upcoming, 4)
pagi2 = Paginator(todo_items_completed, 4)
page_num = request.GET.get('page')
page_num2 = request.GET.get('page')
page_obj = pagi1.get_page(page_num)
page_obj2 = pagi2.get_page(page_num2)
if request.method == "POST":
todo_form = TodoForm(request.POST)
if todo_form.is_valid():
data = todo_form.cleaned_data.get('title')
obj = Todo.objects.create(date_created=current, title=data, user_id=request.user)
context = {'todo_form':todo_form, 'page_obj':page_obj, 'page_obj2':page_obj2}
return render(request, 'todo/main.html', context)
main.html
{% extends 'todo/index.html' %}
{% load crispy_forms_tags %}
{% block content %}
<nav aria-label="...">
<ul class="pagination justify-content-center">
<!-- pagination - previous pages -->
{% if page_obj.has_previous or page_obj2.has_previous %}
<li class="page-item">
{% if page_obj.has_previous %}
<a class="page-link" href="?page={{ page_obj.previous_page_number }}" tabindex="-1">«</a>
{% else %}
<a class="page-link" href="?page={{ page_obj2.previous_page_number }}" tabindex="-1">«</a>
{% endif %}
</li>
{% endif %}
<!-- pagination - current page -->
<li class="page-item active">
<a class="page-link" href="?page={{ page_obj.number }}">{{ page_obj.number }}</a>
</li>
<!-- pagination - Next pages -->
{% if page_obj.has_next or page_obj2.has_next %}
<li class="page-item">
{% if page_obj.has_next %}
<a class="page-link" href="?page={{ page_obj.next_page_number }}">»</a>
{% else %}
<a class="page-link" href="?page={{ page_obj2.next_page_number }}">»</a>
{% endif %}
</li>
{% endif %}
</ul>
</nav>
<div class="center-column">
<h2 class="heading" style="text-align: center;">Hello {{ request.user.username }}, Here's your ToDo List</h2>
<form action="" method="POST" id='form-create'>
{% csrf_token %}
<div style="text-align: center;">
{{ todo_form.title }}
<button type="submit" class="form-control btn btn-primary mb-3 mr-sm-2">Add Items</button>
</div>
</form>
<h4 class="heading" style="text-align: center;">Upcoming ToDo Items</h4><br>
<div class="row">
<div class="col" id="upcomItem">
<ul class="list-group" id="upcomingItems">
{% for i in page_obj %}
<li class="list-group-item list-group-item-primary mb-2" id="upcomingItem">{{ i.title }}
<div class="float-right">
<button type="submit" class="btn-sm btn-danger ml-2 mt-2 mr-2 mb-1">Delete</button>
</div>
<div class="float-right">
<button type="submit" class="btn-sm btn-success ml-2 mt-2 mr-2 mb-1" id="update_btn">Update</button>
</div>
<div class="float-right">
<button type="submit" class="btn-sm btn-dark ml-2 mt-2 mr-2 mb-1" id="completed_btn">Completed</button>
</div>
</li>
{% endfor %}
</ul>
</div>
</div>
<hr style="border-top: 1px solid #999; ">
<div class="row">
<div class="col">
<h4 class="heading" style="text-align: center;">Completed ToDo Items</h4>
<ul class="list-group" id='compItems'>
{% for i in page_obj2 %}<hr>
<li class="list-group-item list-group-item-primary mb-2" id="upcomingItem">{{ i.title }}
<div class="float-right">
<button type="submit" class="btn-sm btn-danger ml-2 mt-2 mr-2 mb-1">Delete</button>
</div>
<div class="float-right">
<button type="submit" class="btn-sm btn-success ml-2 mt-2 mr-2 mb-1" >Update</button>
</div>
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endblock %}
At first I have used or in template tags in if condition I got this error. Error Message occurs when I try to add new to-do item
I tried and operator in template tags I didn;'t even get page-2 link eventhough I have upcoming items and no extra completed items.
Use or operator as #Willem pointed. And you active link href must be {{ page_obj.number }} instead {{ page_obj.page_number }}:
<li class="page-item active">
<a class="page-link" href="?page={{ page_obj.number }}">{{ page_obj.number }}</a>
</li>
As you can see your error EmptyPage raised in your template at line 18
Your conditions should be a disjunction of the conditions of the paginators, so or instead of and:
{% if page_obj.has_previous or page_obj2.has_previous %}
…
{% endif %}
the same for .has_next. The previous and next page then should be handled by checking which page object has a next page, so:
{% if page_obj.has_next or page_obj2.has_next %}
<li class="page-item">
{% if page_obj.has_next %}
<a class="page-link" href="?page={{ page_obj.next_page_number }}">»</a>
{% else %}
<a class="page-link" href="?page={{ page_obj2.next_page_number }}">»</a>
{% endif %}
</li>
{% endif %}
That being said, I'm not sure this provides the best user experience. Perhaps it is better to make two separate paginations (so work with ?pagedone=…&pagetodo=…).

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?

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: