Infinite scroll with Django
Tags: django, python, javascript, webdev
Published: 2019-08-15 18:08:31

This post cross-published with [OnePublish](https://www.onepubli.sh)

<p> Today I am going to show you quick tutorial about how to create endless pagination or infinite scroll with Django</p>
<p> 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.</p>
<p>Alright! Let's launch our infinite-scroll-django rocket!</p>

<p> I am assuming that you already created your project</p>

<h4> Step 1: Creating our model </h4>
<p> We are going to create very simple blog with posts. Let's create our post model in <b>models.py</b></p>
```python
   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
  
   
```
<p>Don't forget to migrate your model :)</p>

<h4>Step 2: Creating our view</h4>
<p>In <b>views.py</b> we are going to import <b>ListView</b>, it is a  class-based view and it will contain the list of objects.</p>

```python
  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']
```
<p>As you see I will load 2 posts per scroll by using <b>paginate_by</b> attribute but you can change it how many you want. The <b>context_object_name</b> 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.</p>

<h4>Step 3: URL Configuration</h4>
<p>Time to configure our <b>urls.py</b>, so let's see the code first.</p>
```python
  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)

```
<p>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.</p>
<p>Just reminder <b>static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)</b> is for serving media files.</p>

<h4>Step 4: Waypoints JS and Template </h4>
<p>Waypoints is a small jQuery plugin that makes it easy to execute a function whenever you scroll to an element.</p>
[Documentation of Waypoints](http://imakewebthings.com/waypoints/shortcuts/infinite-scroll/)
<p>Alright! Let's see the code first</p>
```html
       
            <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>


```
<p>This is the main part of tutorial, we are first including <b>jquery-2.2.4.min.js</b>. It is better to include 2.2.4 version of jQuery otherwise it will cause errors. Then add <b>jquery.waypoints.min.js</b> and <b>infinite.min.js</b></p>
<p>You can get scripts from directly github repo of waypoints.</p>
[jquery.waypoints.min.js](https://github.com/imakewebthings/waypoints/tree/master/lib)
[infinite.min.js](https://github.com/imakewebthings/waypoints/tree/master/lib/shortcuts)

<p><b>element</b> 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.</p>

<p><b>.infinite-more-link</b> is matching the "Next Page" element on every page.</p>

<p><b>.infinite-item</b> is a selector string that should match the individual items that will be pulled out of each page and appended to the item container.</p>

<p><b>offset</b> 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.</p>

<p>PageLoad functions is for display spinner while posts are loading</p>

<h4>Mission Accomplished!</h4>
 [Infinite Scroll Project](https://github.com/raszidzie/infinite-scroll)
 <p>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! </p>


<h4><b>Stay Connected!</b></h4>
{% tag django %}