This post cross-published with OnePublish
Today I am going to show you quick tutorial about how to create endless pagination or infinite scroll with Django
There are many sources on internet related with this topic but majority of them are not fully explained. So, I will try to explain it clearly and step by step for you.
Alright! Let's launch our infinite-scroll-django rocket!
I am assuming that you already created your project
Step 1: Creating our model
We are going to create very simple blog with posts. Let's create our post model in models.py
from django.db import model
class Post(models.Model):
title = models.CharField(max_length=250)
description = models.TextField()
image = models.FileField(null=True, blank=True)
def __str__(self):
return self.title
Don't forget to migrate your model :)
Step 2: Creating our view
In views.py we are going to import ListView, it is a class-based view and it will contain the list of objects.
from django.shortcuts import render
from .models import Post
from django.views.generic.list import ListView
class PostsView(ListView):
model = Post
paginate_by = 2
context_object_name = 'posts'
template_name = 'posts.html'
ordering = ['title']
As you see I will load 2 posts per scroll by using paginate_by attribute but you can change it how many you want. The context_object_name attribute specifies the name of variable to access from templates. Providing a useful context_object_name is always a good idea. Your coworkers who design templates will thank you. In addition, you can order posts by title or published date but for now let's keep it title.
Step 3: URL Configuration
Time to configure our urls.py, so let's see the code first.
from django.contrib import admin
from django.urls import path
from posts.views import PostsView
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('', PostsView.as_view(), name="posts"),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
In class-based views, you have to call as_view() function so as to return a callable view that takes a request and returns a response. Its the main entry-point in request-response cycle in case of generic views.
Just reminder static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) is for serving media files.
Step 4: Waypoints JS and Template
Waypoints is a small jQuery plugin that makes it easy to execute a function whenever you scroll to an element.
Alright! Let's see the code first
<div class="container">
<div class="row infinite-container">
{% for post in posts %}
<div class="col-md-6 infinite-item">
<div class="card mb-4 shadow-sm">
<img class="img-thumbnail" src="{{post.image.url}}"/>
<div class="card-body">
<h5>{{post.title}}</h5>
<p class="card-text">
{{post.description|truncatewords:20}}
</p>
</div>
</div>
</div>
{% endfor %}
</div>
{% if page_obj.has_next %}
<a class="infinite-more-link" href="?page={{ page_obj.next_page_number }}"></a>
{% endif %}
<div class="d-flex justify-content-center" style="display:none;">
<div class="spinner-border" role="status">
<span class="sr-only">Loading...</span>
</div>
</div>
</div>
<script src="/static/js/jquery-2.2.4.min.js"></script>
<script src="/static/js/jquery.waypoints.min.js"></script>
<script src="/static/js/infinite.min.js"></script>
<script>
var infinite = new Waypoint.Infinite({
element: $('.infinite-container')[0],
handler: function(direction) {
},
offset: 'bottom-in-view',
onBeforePageLoad: function () {
$('.spinner-border').show();
},
onAfterPageLoad: function () {
$('.spinner-border').hide();
}
});
</script>
This is the main part of tutorial, we are first including jquery-2.2.4.min.js. It is better to include 2.2.4 version of jQuery otherwise it will cause errors. Then add jquery.waypoints.min.js and infinite.min.js
You can get scripts from directly github repo of waypoints.
jquery.waypoints.min.js
infinite.min.js
element option for Infinite referes to the container around all infinite items that will be used as the waypoint and fetched items will be appended to.
.infinite-more-link is matching the "Next Page" element on every page.
.infinite-item is a selector string that should match the individual items that will be pulled out of each page and appended to the item container.
offset is the same offset option from a regular Waypoint, except the default is now 'bottom-in-view' instead of 0. This means, by default, new items will be loaded when the bottom of the container comes into view.
PageLoad functions is for display spinner while posts are loading
Mission Accomplished!
You just learned something very useful today and launched your infinite-scroll-django rocket! You can clone or download this project from my git repository and don't forget to follow me on social media, join Reverse Astronauts community!
Top comments (6)
Take a look how intercoolerjs do the same on example section
sure I will Thanks! :)
after two days of trying to make this infinite scrolling work I came across your tutorial. Thanks my friend
can you help me It's not working for me I have been working on this for 1 week
Somebody Please can help me it's not working
Really useful information