How to load more data on a button click in Django

In this article, we will learn how to create endless pagination or load more data on a button click. Loading all the data at once is not a good option, imagine if you have thousands of gigabytes of data and you are loading it simultaneously, not only it will load slowly but also decrease the overall user experience.

So it’s always a good idea to load the data in small chunks and if the user wants to see more, then load more data.

youtube tutorial

Project Setup

Create a basic model with title and description field and register the model

from django.db import models 
# Create your models here.  
class Post(models.Model):    
    title = models.CharField(max_length=50)    
    desc = models.CharField(max_length=300, blank=True, null=True)       
    def __str__(self) -> str:        
        return self.title

Now simply create a function in your to render the data in your HTML file.

from myapp.models import Post
from django.shortcuts import render
from django.http import JsonResponse
# Create your views here.  
def index(request):    
    post_obj = Post.objects.all()[0:5]    
    total_obj = Post.objects.count()       
    return render(request, 'index.html', context={'posts': post_obj, 'total_obj': total_obj})

Let say we have a total of 10 objects in our model, so in the index function, we are only rendering 5 and the rest will be rendered when the user wants them to be rendered.

Now create an HTML file and send an ajax request for loading more posts.

Learn more about ajax request here


<html lang="en">

    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Infinite Scroll</title>
    <link rel="stylesheet" href=""
        integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">

    <!-- Latest compiled and minified JavaScript -->
    <script src=""></script>
    <script src="[email protected]/dist/umd/popper.min.js"
    <script src=""
    .not-visible {
        display: none;

    <div class="container">
        <div class="content" id="content">
            {% for post in posts %}
            <div class="single_content border border-success mt-2 pl-2">
            {% endfor %}
        <div class="spinner-border text-primary mt-2 not-visible" role="status" id="spinner">
            <span class="sr-only">Loading...</span>
        <div class="load-more__btn mt-3" id="btn">
            <button type="button" class="btn btn-success">Load More Post</button>
        <div class="alert alert-danger mt-2 not-visible" role="alert" id='alert'>
            No more post to load!!
        // var _current_item = $('.single_content').length
        // console.log(_current_item);
        const loadBtn = document.getElementById('btn');
        const spinner = document.getElementById('spinner');
        const total = JSON.parse(document.getElementById('json-total').textContent);
        const alert = document.getElementById('alert');

        function loadmorePost() {
            var _current_item = $('.single_content').length
            const content_container = document.getElementById("content");
                url: '{% url "load" %}',
                type: 'GET',
                data: {
                    'loaded_item': _current_item
                beforeSend: function () {
                success: function (response) {
                    const data = response.posts
           => {
                        content_container.innerHTML += `<div class="single_content border border-success mt-2 pl-2">
                    if (_current_item == total) {
                    } else {
                error: function (err) {
        loadBtn.addEventListener('click', () => {


Here on click of “loadBtn”, the loadmorePost() function is called to load more posts.

Now create a function to handle this request.

def load_more(request):    
    loaded_item = request.GET.get('loaded_item')    
    loaded_item_int = int(offset)    
    limit = 2    
    post_obj = list(Post.objects.values() [loaded_item_int:loaded_item_int+limit])    
    data = {'posts': post_obj}    
    return JsonResponse(data=data)

For Demo of the Project visit youtube channel

Here in this function loaded_item are the number of items that are already loaded and the limit is the number of item to be loaded after a button click.

for a complete and detailed tutorial visit youtube

Follow me on Github for more

Happy Coding!!!


Leave a Reply