How to paginate bootstrap cards with django - django

I am getting my query results based on user selection and showing them on bootstrap cards in django. I am using django Paginator to display at max 6 results per page (currently set to 1 for testing). The problem is my Paginator is showing all the results on all the pagination pages.
Could someone please help me??
View:
def results(request):
results = []
query_city = request.GET.get('city')
print(query_city)
all_records = hotel.objects.all()
for states in all_records:
if states.confirm_approval and states.space_state == query_city:
print(states)
results.append(states)
paginator = Paginator(results,1)
page = request.GET.get('page')
try:
items = paginator.page(page)
except PageNotAnInteger:
items = paginator.page(1)
except EmptyPage:
items = paginator.page(paginator.num_pages)
index = items.number - 1
max_index = len(paginator.page_range)
start_index = index - 5 if index >= 5 else 0
end_index = index + 5 if index <= max_index - 5 else max_index
page_range = paginator.page_range[start_index:end_index]
context = {
'results':results,
'items':items,
'page_range':page_range,
}
return render(request, 'results/results.html', context)
Html Template:
% for result in results %}
{% if forloop.counter0|divisibleby:3 %} <div class="row"> {% endif %}
<div class="col">
<div class="card-deck" id="cardholder">
<div class="card" style="max-width: 20rem;">
<img class="card-img-top" src="{% static 'mainpage/img/bg/books.jpg' %}" alt="Card image cap">
<div class="card-body">
<h5 class="card-title">{{ result.hotel_name }}</h5>
</div>
<div class="card-footer">
Show more
</div>
</div>
</div>
</div>
{% if forloop.counter|divisibleby:3 or forloop.last %}</div><!-- row closing -->{% endif %}
{% endfor %}
{% if items.has_other_pages %}
<nav aria-label="">
<ul class="pagination justify-content-center">
{% if items.has_previous %}
<li class=class="page-item">
<a class="page-link"
href="?page={{items.previous_page_number}}{% if request.GET.city %}&city={{ request.GET.city }}{% endif %}"
tabindex="-1">Previous</a>
</li>
{% else %}
<li class="page-item disabled"><a class="page-link">Previous</a></li>
{% endif %}
{% for i in page_range %}
{% if items.number == i %}
<li class="page-item active"><a class="page-link" href="#">{{i}} <span
class="sr-only">(current)</span></a>
</li>
{% else %}
<li class="page-item"><a class="page-link"
href="?page={{i}}{% if request.GET.city %}&city={{ request.GET.city }}{% endif %}">{{i}}</a>
</li>
{% endif %}
{% endfor %}
{% if items.has_next %}
<li class="page-item">
<a class="page-link" aria-label="Next"
href="?page={{items.next_page_number}}{% if request.GET.city %}&city={{ request.GET.city }}{% endif %}">Next</a>
</li>
{% else %}
<li class="page-item disabled"><a class="page-link">Next</a></li>
{% endif %}
</ul>
</nav>
{% endif %}

brtt3000 from r/djangolearning helped me over redit.
This was his answer: You're looping over the wrong context variable,
change it to items.
{% for result in results %} I suspected this as soon as I saw you had
both items and results in the context :)
For anyone whos gets here, remember to pass in the paginated variable.

Related

Paginator won't paginate

I use Paginator for paginate my posts, i have no error, and i have the list of page in the bottom of the posts, but:
1.Post doesn't paginate correctly, i have set 5 i have more.
2. When i click on the 2 second page and 3 and etc, i have the same results of posts, i have no the next page with nexts posts.
This is my view code:
def post_all(request):
posts = Post.objects.filter().order_by('-published_date')
paginator = Paginator(posts, 5)
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
categories = PostCategory.objects.all().annotate(posts_count=Count('post'))
return render(request, 'front/blog/post_all.html', {"posts":posts, "categories":categories,"page_obj":page_obj})
My template:
<!-- Pagination -->
<div class="pagination">
{% if page_obj.has_previous %}
<i class="fa fa-angle-left"></i>
{% endif %}
{{ page_obj.number }} de {{ page_obj.paginator.num_pages }}
{% if page_obj.has_next %}
<i class="fa fa-angle-right"></i>
{% endif %}
</div>
<!-- End Pagination -->
Thank u.
You could try using Class-based views.
Yours would be something like this :
views.py
from django.views.generic import (ListView)
class PostAllView(ListView):
model = Post
template_name = 'front/blog/post_all.html' # <app>/<model>_<viewtype>.html
context_object_name = 'posts'
ordering = ['-published_date']
paginate_by = 5
and a template.html that you can adapt to yours:
<h1>Total of posts : {{ page_obj.paginator.count }}</h1>
{% for post in posts %}
<article>
<p class="article-content">{{ post.content }}</p>
<!-- all the post related content you want to display here-->
</article>
{% endfor %}
{% if is_paginated %}
{% if page_obj.has_previous %}
<!-- you can adapt the class to your use-->
<a class="button" href="?page=1">First</a>
<a class="button" 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="button-strong" href="?page={{ num }}">{{ num }}</a>
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
<a class="button" href="?page={{ num }}">{{ num }}</a>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<a class="button" href="?page={{ page_obj.next_page_number }}">Next</a>
<a class="button" href="?page={{ page_obj.paginator.num_pages }}">Last</a>
{% endif %}
{% endif %}

How to add paginator and filter in your website?

I'm doing a project in which I need to display cars and the user is allowed to filter their queries based on price, make, model etc. Earlier today the filter was not working but the Paginator was, but now, the filter is working and the paginator is not. I've been stuck on this the whole day and I don't know what else to do.
This is my code:
views.py
def posts(request):
cars = Userpost.objects.all()
myFilter = UserpostFilter(request.GET, queryset=cars)
cars = myFilter.qs
p = Paginator(Userpost.objects.all(), 2)
page = request.GET.get('page')
cars_list = p.get_page(page)
nums = "a" * cars_list.paginator.num_pages
context = {'cars':cars, "myFilter":myFilter, 'cars_list':cars_list, "nums":nums}
return render(request, 'store/userposts.html', context)
userposts.html
{% extends 'store/main.html' %}
{% load static %}
{% block content %}
<div class = 'row'>
<div class = 'col'>
<div class = 'card card-body'>
<form method="get">
{{myFilter.form}}
<button class="btn btn-primary" type = "submit">Search</button>
</form>
</div>
</div>
</div>
<div class="row">
{% for car in cars %}
<div class="col-lg-4">
<img class="thumbnail" src="{{car.imageURL|default:'/images/transparentLogo.png'}}">
<div class="box-element product">
<h6><strong>{{car.Year}} {{car.Make}} {{car.Model}}</strong></h6>
<hr>
<a class="btn btn-outline-success" href="{% url 'post_detail' car.pk %}">View</a>
<h4 style="display: inline-block; float: right"><strong>${{car.Price|floatformat:2}}</strong></h4>
</div>
</div>
{% endfor %}
</div>
<nav aria-label="Page navigation"> <ul class="pagination">
{% if cars_list.has_previous %}
<li class="page-item">
<a class="page-link" href="?page=1" aria-label="Previous">
<span aria-hidden="true">«</span>
<span class="sr-only">begin</span>
</a>
</li> {% endif %}
{% for n in cars_list.paginator.page_range %}
{% if cars_list.number == n %}
<li class="page-item active">
<span class="page-link">{{ n }}<span class="sr-only">(current)</span></span>
</li>
{% elif n > cars_list.number|add:'-3' and n < cars_list.number|add:'3' %}
<li class="page-item"><a class="page-link" href="?page={{ n }}">{{ n }}</a></li>
{% endif %}
{% endfor %}
{% if cars_list.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ cars_list.paginator.num_pages }}" aria-label="Next">
<span aria-hidden="true">»</span>
<span class="sr-only">end</span>
</a>
</li>
{% endif %} </ul> </nav>
<br/>
{% endblock content %}
filters.py
class UserpostFilter(django_filters.FilterSet):
start_date = DateFilter(field_name = "date_published", lookup_expr = 'gte')
end_date = DateFilter(field_name = "date_published", lookup_expr = 'lte')
min_price = django_filters.NumberFilter(field_name="Price", lookup_expr='gte')
max_price = django_filters.NumberFilter(field_name="Price", lookup_expr='lte')
class Meta:
model = Userpost
field = '__all__'
exclude = 'image', 'user', 'Price', 'Email', 'date_published'
I noticed that when i change the for loop on userposts.html to do "for car in cars_list", the pagination works but it breaks the filter, and using "for car in cars" makes the filter works but the pagination breaks.
I don't know what to do about it and I would really appreciate some help
try this
def posts(request):
cars = Userpost.objects.all()
myFilter = UserpostFilter(request.GET, queryset=cars)
if myFilter.qs:
cars = myFilter.qs
paginator = Paginator(cars, 2)
page = request.GET.get('page')
try:
cars = paginator.page(page)
except PageNotAnInteger:
cars = paginator.page(1)
except EmptyPage:
cars = paginator.page(paginator.num_pages)
context = {'cars_list':cars, "myFilter":myFilter}
return render(request, 'store/userposts.html', context)
template
{% extends 'store/main.html' %}
{% load static %}
{% block content %}
<div class = 'row'>
<div class = 'col'>
<div class = 'card card-body'>
<form method="get">
{{myFilter.form}}
<button class="btn btn-primary" type = "submit">Search</button>
</form>
</div>
</div>
</div>
<div class="row">
{% for car in cars_list %}
<div class="col-lg-4">
<img class="thumbnail" src="{{car.imageURL|default:'/images/transparentLogo.png'}}">
<div class="box-element product">
<h6><strong>{{car.Year}} {{car.Make}} {{car.Model}}</strong></h6>
<hr>
<a class="btn btn-outline-success" href="{% url 'post_detail' car.pk %}">View</a>
<h4 style="display: inline-block; float: right"><strong>${{car.Price|floatformat:2}}</strong></h4>
</div>
</div>
{% endfor %}
</div>
<nav aria-label="Page navigation"> <ul class="pagination">
{% if cars_list.has_previous %}
<li class="page-item">
<a class="page-link" href="?page=1" aria-label="Previous">
<span aria-hidden="true">«</span>
<span class="sr-only">begin</span>
</a>
</li> {% endif %}
{% for n in cars_list.paginator.page_range %}
{% if cars_list.number == n %}
<li class="page-item active">
<span class="page-link">{{ n }}<span class="sr-only">(current)</span></span>
</li>
{% elif n > cars_list.number|add:'-3' and n < cars_list.number|add:'3' %}
<li class="page-item"><a class="page-link" href="?page={{ n }}">{{ n }}</a></li>
{% endif %}
{% endfor %}
{% if cars_list.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ cars_list.paginator.num_pages }}" aria-label="Next">
<span aria-hidden="true">»</span>
<span class="sr-only">end</span>
</a>
</li>
{% endif %} </ul> </nav>
<br/>
{% endblock content %}

Django Pagination - Object list not looping in template

I'm attempting to use pagination on my notifications page for a user (list of all notifications). When I add the code for pagination:
def notificationList(request, pk):
notifications = Notification.objects.all()
paginator = Paginator(notifications, 5)
page = request.GET.get('page')
try:
notifications = paginator.page(page)
except PageNotAnInteger:
notifications = paginator.page(1)
except EmptyPage:
notifications = paginator.page(paginator.num_pages)
context = {'notifications': notifications }
return render(request, 'user/notifications.html', context)
The result is this:
However, when I comment out all pagination related code in views.py, all the notifications appear on the page (pagination appears). So I know it's not that I'm not accessing my notification object list incorrectly/returning an empty queryset. Here is the notifications.html pagination code:
{% if notifications.has_other_pages %}
<ul class="pagination justify-content-center mb-4">
{% if notifications.has_previous %}
<li class="page-item"><a class="page-link" href="?page={{ notifications.previous_page_number }}">«</a></li>
{% else %}
<li class="disabled page-item"><span class="page-link">«</span></li>
{% endif %}
{% for i in notifications.paginator.page_range %}
{% if notifications.number == i %}
<li class="active page-item"><span class="page-link">{{ i }} <span class="sr-only page-item">(current)</span></span></li>
{% else %}
<li class="page-item"><a class="page-link" href="?page={{ i }}">{{ i }}</a></li>
{% endif %}
{% endfor %}
{% if notifications.has_next %}
<li class="page-item"><a class="page-link" href="?page={{ notifications.next_page_number }}">»</a></li>
{% else %}
<li class="disabled page-item"><span class="page-link">»</span></li>
{% endif %}
</ul>
{% endif %}
Here is where I render the notifications in the template:
{% for notification in notifications %}
<div class="row">
<div class="col">
{% if notification.read == False %}
<span class="badge badge-primary">New</span>
{% elif notification.read == True %}
<span class="badge badge-success">Read</span>
{% endif %}
</div>
<div class="col">
<a class="btn btn-sm btn-info" href="{% url 'offer-details' notification.offer_id %}">View</a>
</div>
<div class="col">
{% if notification.type_of_notification == "O" %}
<p>An offer has been made for one of your repairs!</p>
{% elif notification.type_of_notification == "P" %}
<p>A payment has been made on a repair!</p>
{% elif notification.type_of_notification == "OR" %}
<p>Sorry, your offer for a repair has been rejected.</p>
{% elif notification.type_of_notification == "OC" %}
<p>An offer for your repair has been canceled!</p>
{% endif %}
</div>
<div class="col">
{{notification.created_at}}
</div>
</div>
<hr>
{% endfor %}

How to shorten Pagination in Django

I have a Django project with 600 listings. I get an extremely long pagination and I would like to know how I would shorten the pagination. Maybe not show all the page numbers and replace some with ... I am using bootstrap v4 and django 1.10. I know there are modules out there I could use but I want to learn.
template
{% if product.has_other_pages %}
<div class="col-md-12 text-center">
<nav aria-label="">
<ul class="pagination">
{% if product.has_previous %}
<li class="page-item"><a class="page-link"
href="?page={{ product.previous_page_number }}">«</a>
</li>
{% else %}
<li class="page-item disabled"><a class="page-link"><span>«</span></a></li>
{% endif %}
{% for i in product.paginator.page_range %}
{% if product.number == i %}
<li class="page-item active"><a class="page-link" href="#">{{ i }} <span
class="sr-only">(current)</span></a></li>
{% else %}
<li class="page-item"><a class="page-link" href="?page={{ i }}">{{ i }}</a></li>
{% endif %}
{% endfor %}
{% if product.has_next %}
<li class="page-item"><a class="page-link" aria-label="Next"
href="?page={{ product.next_page_number }}">»</a></li>
{% else %}
<li class="page-item disabled"><a class="page-link"><span>»</span></a></li>
{% endif %}
</ul>
</nav>
</div>
{% endif %}
views
def products_all(request):
products = Product.objects.order_by("-date_added")
product_count = Category.objects.annotate(num_products=Count('product')).order_by('-num_products')[:5]
company_count = Company.objects.annotate(num_products=Count('product')).order_by('-num_products')[:5]
manufacturer_count = Manufacturer.objects.annotate(num_products=Count('product')).order_by('-num_products')[:5]
total_manufacturer = Manufacturer.objects.count()
total_company = Company.objects.count()
total_categories = Category.objects.count()
paginator = Paginator(products, 50)
page = request.GET.get('page')
try:
product = paginator.page(page)
except PageNotAnInteger:
product = paginator.page(1)
except EmptyPage:
product = paginator.page(paginator.num_pages)
template = "products/all.html"
context = {'product': product,
'products': products,
'product_count': product_count,
'company_count': company_count,
'manufacturer_count': manufacturer_count,
'total_categories': total_categories,
'total_company': total_company,
'total_manufacturer': total_manufacturer
}
return render(request, template, context)

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: