Django pagination is not working properly with very large dataset - python

When I use pagination with a very large dataset, it works too slow. Maybe I am not implementing it properly. Please help. How to make it fast? Is there anything that I can change or implement so that it works fine?
view.py
def display(request):
user_list = Final.objects.all()
searchlen= user_list.count()
paginator = Paginator(user_list, 100)
page = request.GET.get('page')
users = paginator.get_page(page)
return render(request,'displayLogs.html',{'users': users,'searchlen':searchlen})
model.py
class Final(models.Model):
name = models.TextField(db_column='Date',primary_key=True, blank=True, null=False) # Field name made lowercase.
corr = models.TextField(db_column='CorrelationId', blank=True, null=True) # Field name made lowercase.
<tbody>
<tr class="gradeX">
{% for item in users %}
<td>{{item.dat}}</td>
<td>{{item.act}}</td>
<td>{{item.actor}}</td>
<td class="center">{{item.tar}}</td>
</tr>
{% endfor %}
</tbody>
<div class="pagination" style="border-style:inset;border-width:5px;padding-bottom: 5px">
{% if users.has_previous %}
<a class="pagination-action" href="?page=1"> <i class="fas fa-angle-double-left"></i></a>
<a class="pagination-action" href="?page={{ users.previous_page_number}}"> <i class="fas fa-angle-left"></i></a>
{% endif %}
{% for num in users.paginator.page_range %}
{% if users.number == num %}
<span class="pagination-number pagination-current"><strong>{{ num }}</strong></span>
{% elif num > users.number|add:'-3' and num < users.number|add:'3' %}
<a class="pagination-number" href="?page={{ num }}">{{num}}</a>
{% endif %}
{% endfor %}
{% if users.has_next %}
<a class="pagination-action" href="?page={{ users.next_page_number }}"><i class="fas fa-angle-right"></i></a>
<a class="pagination-action" href="?page={{ users.paginator.num_pages }}"> <i class="fas fa-angle-double-right"> </i></a>
{% endif %}
</div>

I suggest doing something like this for large dataset. I attach my design as given below. Here click << to go first page , >> to go last page , < to go previous page and > to go next page.
<tbody>
{% for item in users %}
<tr class="gradeX">
<td>{{item.dat}}</td>
<td>{{item.act}}</td>
<td>{{item.actor}}</td>
<td class="center">{{item.tar}}</td>
</tr>
{% endfor %}
</tbody>
<nav aria-label="pagination" class="pagination_area">
<div class="row">
{% if users.end_index > 0 %}
<div class="col-sm-12 col-md-5 d-none d-md-block">
<p>Showing {{ users.start_index }} to {{ users.end_index }} of {{ users.paginator.count}}.</p>
</div>
{% endif %}
{% if users.paginator.num_pages > 1 %}
<div class="col-sm-12 col-md-7 dataTables_pager">
<ul class="pagination">
{% if users.has_previous %}
<li class="page-item">
<a class="page-link" data-page="1" href="?page={{ users.previous_page_number }}">
<i class="fa fa-angle-double-left"></i>
</a>
</li>
{% if users.previous_page_number > 1 %}
<li class="page-item">
<a class="page-link " data-page="{{users.previous_page_number}}" href="?page={{ users.previous_page_number }}">
<i class="fa fa-angle-left"></i>
</a>
</li>
{% endif %}
{% endif %}
{% if users.previous_page_number > 2 %}
<li class="page-item">
<a class="page-link " data-page="{{users.number|add:'-2'}}" href="?{{users.number|add:'-2'}}"> {{ users.number|add:"-2" }} </a>
</li>
<li class="page-item">
<a class="page-link " data-page="{{users.number|add:'-1'}}" href="?page={{users.number|add:'-1'}}"> {{ users.number|add:"-1" }} </a>
</li>
{% endif %}
<li class="page-item active"><span class="page-link ">{{ users.number }}</span></li>
{% if users.paginator.num_pages > users.number|add:"2" %}
<li class="page-item">
<a class="page-link " data-page="{{users.number|add:'1'}}" href="?page={{users.number|add:'1'}}"> {{ users.number|add:"1" }} </a>
</li>
<li class="page-item">
<a class="page-link " data-page="{{users.number|add:'2'}}" href="?page={{users.number|add:'2'}}"> {{ users.number|add:"2" }} </a>
</li>
{% endif %}
{% if users.has_next %}
<li class="page-item">
<a class="page-link " data-page="{{users.next_page_number}}" href="?page={{ users.next_page_number }}">
<i class="fa fa-angle-right"></i>
</a>
</li>
<li class="page-item">
<a class="page-link " data-page="{{users.paginator.num_pages}}" href="?page={{users.paginator.num_pages}}">
<i class="fa fa-angle-double-right"></i>
</a>
</li>
{% endif %}
</ul>
</div>
{% endif %}
</div>
</nav>
This is my design. You can change design for your requirement.

Related

Pagination button not highlighting the current page

So I'm trying to make a button which highlights as active when the page is the same as page number, but it does not work, It only highlights page 1, When I go to page 2 then page 1 is still highlighed, index function handles the page I'm talking about.
views.py
from django.shortcuts import render
from .models import Listing
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
# Create your views here.
def index(request):
listings = Listing.objects.all()
paginator = Paginator(listings, 3)
page = request.GET.get('page')
paged_listings = paginator.get_page(page)
params = {'listings':paged_listings}
return render(request, 'listings/listings.html', params)
def listing(request, listing_id):
return render(request, 'listings/listing.html')
def search(request):
return render(request, 'listings/search.html')
listings.html
{% extends 'base.html' %}
{% block content %}
{% load humanize %}
<!-- Breadcrumb -->
<section id="bc" class="mt-3">
<div class="container">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="{% url 'index' %}">
<i class="fas fa-home"></i> Home</a>
</li>
<li class="breadcrumb-item active"> Browse Listings</li>
</ol>
</nav>
</div>
</section>
<!-- Listings -->
<section id="listings" class="py-4">
<div class="container">
<div class="row">
{% if listings %}
{% for listing in listings %}
<div class="col-md-6 col-lg-4 mb-4">
<div class="card listing-preview">
<img class="card-img-top" src="{{ listing.photo_main.url }}" alt="">
<div class="card-img-overlay">
<h2>
<span class="badge badge-secondary text-white">${{ listing.price | intcomma}}</span>
</h2>
</div>
<div class="card-body">
<div class="listing-heading text-center">
<h4 class="text-primary">{{ listing.title }}</h4>
<p>
<i class="fas fa-map-marker text-secondary"></i>{{ listing.city }} {{ listing.state }}, {{ listing.zipcode }}</p>
</div>
<hr>
<div class="row py-2 text-secondary">
<div class="col-6">
<i class="fas fa-th-large"></i>Sqfit: {{ listing.sqft }}</div>
<div class="col-6">
<i class="fas fa-car"></i>Garage: {{ listing.garage }}</div>
</div>
<div class="row py-2 text-secondary">
<div class="col-6">
<i class="fas fa-bed"></i>Bedrooms: {{ listing.bedrooms }}</div>
<div class="col-6">
<i class="fas fa-bath"></i>Bathrooms: {{ listing.bathrooms }}</div>
</div>
<hr>
<div class="row py-2 text-secondary">
<div class="col-12">
<i class="fas fa-user"></i>{{ listing.realtor.name }}</div>
</div>
<div class="row text-secondary pb-2">
<div class="col-6">
<i class="fas fa-clock"></i>{{ listing.list_date | timesince }}</div>
</div>
<hr>
More Info
</div>
</div>
</div>
{% endfor %}
{% else %}
<div class="col-md-12">
<p>No Listings Available</p>
</div>
{% endif %}
<!-- Footer -->
<div class="row">
<div class="col-md-12">
{% if listings.has_other_pages %}
<ul class="pagination">
{% if listings.has_previous %}
<li class="page-item">
«
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link">«</a>
</li>
{% endif %}
</ul>
{% endif %}
{% for i in listings.paginator.page_range %}
{% if listings.number == i %}
<li class="page-item active">
<a class="page-link page-item">{{ i }}</a>
</li>
{% else %}
<li class="page-item">
{{i}}
</li>
{% endif %}
{% endfor %}
</div>
</div>
</div>
</section>
{% endblock %}
You mistyped argument in page links. Just replace
<li class="page-item">
{{i}}
</li>
with
<li class="page-item">
{{i}}
</li>
(difference is equal sign = between query parameter and value)
The problem seems to be your use of
{% for i in listings.paginator.page_range %}
As this is returning a range, I think you should be using:
{% for i in listings.paginator %}

Paginator in a view function Django

I'm trying to add the paginate option on my posts page from my blog website. I want to implement the paginator on my view function that renders the page and I found this exemple from Django's doc but it doesn't work. Any help ?
view function:
def blog(request):
posts = Post.objects.all().order_by('-date_posted')
paginator = Paginator(posts, 2)
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
context = {
'posts': posts,
'page_obj': page_obj,
'title': 'Blog',
'banner_page_title': 'Blog',
'page_location': 'Home / Blog'
}
return render(request, 'blog/blog.html', context)
html rendering
<nav class="blog-pagination justify-content-center d-flex">
<ul class="pagination">
{% if is_paginated %}
{% if page_obj.has_previous %}
<li class="page-item">
<a href="?page={{ page_obj.previous_page_number }}" class="page-link" aria-label="Previous">
<span aria-hidden="true">
<span class="ti-arrow-left"></span>
</span>
</a>
</li>
{% endif %}
{% for num in page_obj.paginator.page_range %}
{% if page_obj.number == num %}
<li class="page-item active">
{{ num }}
</li>
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
<li class="page-item">
{{ num }}
</li>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item">
<a href="?page={{ page_obj.next_page_number }}" class="page-link" aria-label="Next">
<span aria-hidden="true">
<span class="ti-arrow-right"></span>
</span>
</a>
</li>
{% endif %}
{% endif %}
</ul>
</nav>
the url route
path('blog/', blog, name='blog'),
Remove the {% if is_paginated %} as it isn't returning any value and that is why you don't see any of the numbers (don't forget to remove the closer if {% endif %})
You can access your paginated objects from the page_obj
{% for post in page_obj %}
{{ post }}
{% endfor %}
Here is the HTML with the changes
{% for post in page_obj %}
{{ post.text }}<br>
{% endfor %}
<nav class="blog-pagination justify-content-center d-flex">
<ul class="pagination">
{% if page_obj.has_previous %}
<li class="page-item">
<a href="?page={{ page_obj.previous_page_number }}" class="page-link" aria-label="Previous">
<span aria-hidden="true">
<span class="ti-arrow-left"></span>
</span>
</a>
</li>
{% endif %}
{% for num in page_obj.paginator.page_range %}
{% if page_obj.number == num %}
<li class="page-item active">
{{ num }}
</li>
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
<li class="page-item">
{{ num }}
</li>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item">
<a href="?page={{ page_obj.next_page_number }}" class="page-link" aria-label="Next">
<span aria-hidden="true">
<span class="ti-arrow-right"></span>
</span>
</a>
</li>
{% endif %}
</ul>
</nav>

Minimise code repetition by creating a reusable template

I have a template which includes 4 different paginators that only differ in context variables (tasks_today, tasks_tomorrow, ... etc.), and I want to minimise code repetition so I don't have 4 different paginator templates.
Template:
<div class="wrapper">
<h3>Today</h3>
<table>
{% if tasks_today %}
{% for task in tasks_today %}
{% include 'todo/task_table_row.html' %}
{% endfor %}
{% include 'todo/paginator_today.html' %}
{% else %}
<p>No tasks for today.</p>
{% endif %}
</table>
<h3>Tomorrow</h3>
<table>
{% if tasks_tomorrow %}
{% for task in tasks_tomorrow %}
{% include 'todo/task_table_row.html' %}
{% endfor %}
{% include 'todo/paginator_tomorrow.html' %}
{% else %}
<p>No tasks for tomorrow.</p>
{% endif %}
</table>
<h3>Upcoming</h3>
<table>
{% if tasks_upcoming %}
{% for task in tasks_upcoming %}
{% include 'todo/task_table_row.html' %}
{% endfor %}
{% include 'todo/paginator_upcoming.html' %}
{% else %}
<p>No upcoming tasks.</p>
{% endif %}
</table>
<h3>Past</h3>
<table>
{% if tasks_past %}
{% for task in tasks_past %}
{% include 'todo/task_table_row.html' %}
{% endfor %}
{% include 'todo/paginator_past.html' %}
{% else %}
<p>No tasks in the past.</p>
{% endif %}
</table>
</div>
paginator_today:
{% load url_replace %}
{% if tasks_today %}
<div class='paginator'>
<nav aria-label="Page navigation">
<ul class="pagination">
{% if tasks_today.has_previous %}
<li class="page-item">
<a class="page-link" href="?{% url_replace page_today=1 %}" aria-label="Previous">
<span aria-hidden="true">«</span>
<span class="sr-only">begin</span>
</a>
</li>
{% endif %}
{% for n in tasks_today.paginator.page_range %}
{% if tasks_today.number == n %}
<li class="page-item active">
<span class="page-link">{{ n }}
<span class="sr-only">(current)</span>
</span>
</li>
{% elif n > tasks_today.number|add:'-3' and n < tasks_today.number|add:'3' %}
<li class="page-item">
<a class="page-link" href="?{% url_replace page_today=n %}">{{ n }}</a>
</li>
{% endif %}
{% endfor %}
{% if tasks_today.has_next %}
<li class="page-item">
<a class="page-link" href="?{% url_replace page_today=tasks_today.paginator.num_pages %}" aria-label="Next">
<span aria-hidden="true">»</span>
<span class="sr-only">end</span>
</a>
</li>
{% endif %}
</ul>
</nav>
</div>
{% endif %}
paginator_tomorrow:
{% load url_replace %}
{% if tasks_tomorrow %}
<div class='paginator'>
<nav aria-label="Page navigation">
<ul class="pagination">
{% if tasks_tomorrow.has_previous %}
<li class="page-item">
<a class="page-link" href="?{% url_replace page_tomorrow=1 %}" aria-label="Previous">
<span aria-hidden="true">«</span>
<span class="sr-only">begin</span>
</a>
</li>
{% endif %}
{% for n in tasks_tomorrow.paginator.page_range %}
{% if tasks_tomorrow.number == n %}
<li class="page-item active">
<span class="page-link">{{ n }}
<span class="sr-only">(current)</span>
</span>
</li>
{% elif n > tasks_tomorrow.number|add:'-3' and n < tasks_tomorrow.number|add:'3' %}
<li class="page-item">
<a class="page-link" href="?{% url_replace page_tomorrow=n %}">{{ n }}</a>
</li>
{% endif %}
{% endfor %}
{% if tasks_tomorrow.has_next %}
<li class="page-item">
<a class="page-link" href="?{% url_replace page_tomorrow=tasks_tomorrow.paginator.num_pages %}" aria-label="Next">
<span aria-hidden="true">»</span>
<span class="sr-only">end</span>
</a>
</li>
{% endif %}
</ul>
</nav>
</div>
{% endif %}
What can I do?
url_replace.py:
from django.utils.http import urlencode
from django import template
​
register = template.Library()
​
#register.simple_tag(takes_context=True)
def url_replace(context, **kwargs):
query = context['request'].GET.dict()
query.update(kwargs)
return urlencode(query)
You can use the with keyword to set certain variables inside your include template:
{% include 'todo/paginator.html' with tasks=tasks_today page='page_today' %}
You can then replace references to tasks_today in you paginator template to tasks, as well as the reference to page_today to page
Edit: The call to url_replace is problematic, since it uses kwargs, and a call like {% url_replace page_today = x %}, will be equivalent to a call to urlreplace(context, **{'page_today' : x}).
Simply calling url_replace with page = x will not work correctly, since it will pass a keyword argument with the name of page instead of the value of page
The naive solution would be to pass a page variable to the paginator.html and call {% urlreplace **{page : 20} %}, but the Django template engine does not allow packing kwargs.
I think the best way to go here is to create a url_replace_single function, since in this use case you only replaces one value.
To do this, you'll need to define a field and value parameter on you url_replace function:
#register.simple_tag(takes_context=True)
def url_replace(context, field, value, **kwargs):
query = context['request'].GET.dict()
query_dict = { field : value}
query.update(query_dict)
return urlencode(query)
Then call the function from your template like this:
{% url_replace field=page value=x %}
The only downside is that this will only let you replace one query parameter in your url.

What's problem with this pagination code?

This code already have done the pagination ,but it false because per page it shows all items in the database ,and the same in other pages
This is the routing
#app.route('/shop/page/<int:page_num>')
def shop(page_num):
products=Product.query.filter
(Product.category.has(Product.category_id))
shopPage=Product.query.paginate
(page=page_num,per_page=5,error_out=True)
return render_template('shop.html',
shopPage=shopPage,products=products)
And this is the HTML code of pagination and the output products of database
{% block content %}
<div class="mb-5">
{% for product in products %}
<div class="col-4 mt-3 ">
<div class="card">
<div class="card-header">
<form method="POST" action="{{ url_for('shop') }}" >
</form>
</div>
<div class="card-body">
<h5 class="card-title">{{product.name }}</h5>
<p class="card-text">
<div>Category: {{ product.category.name }}</div>
<div>Price: {{ product.price }} $</div>
<div>Company: {{ product.company }}</div>
</p>
</div>
</div>
</div>
{% endfor %}
</div>
{% for page in shopPage.iter_pages(left_edge=2, right_edge=2, left_current=1, right_current=2) %}
{% if page %}
<nav >
<ul class="pagination ">
<li class="page-item ">
<a class="page-link" href="{{url_for('shop',page_num=page)}}" tabindex="-1">{{ page }}</a>
</li>
</ul>
</nav>
{% else %}
...
{% endif %}
{% endfor %}
{% endblock %}

Django CMS: How to modify style of show_menu

I want to build a Django CMS template from a template found on https://startbootstrap.com.
I have load the following tags
{% load cms_tags menu_tags sekizai_tags staticfiles %}
and then within the <body> part the menu
...
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
<div class="container">
<a class="navbar-brand" href="#">Start Bootstrap</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
{% show_menu 0 100 100 100 %}
</ul>
</div>
</div>
</nav>
...
Unfortunately, the links for the pages in the menu have almost no CSS (see image).
Basically, the links need to be of class nav-link. How can I fix this?
You can use a custom template for the menu tags;
<ul class="dropdown">
{% show_menu 1 100 100 100 "partials/navigation.html" %}
</ul>
Then in partials/navigation.html;
{% load cms_tags menu_tags cache cms_page %}
{% for child in children %}
<li class="nav-link">
{{ child.get_menu_title }}
{% if child.children %}
<ul class="sub_menu">
{% show_menu from_level to_level extra_inactive extra_active template '' '' child %}
</ul>
{% endif %}
</li>
{% endfor %}
<li class="nav-item">
<a class="nav-link" href="{{ child.attr.redirect_url|default:child.get_absolute_url }}">{{ child.get_menu_title }}</a>
{% if child.children %}
<ul class="sub_menu">
{% show_menu from_level to_level extra_inactive extra_active template '' '' child %}
</ul>
{% endif %}
</li>

Categories