Handling AJAX Requests and Custom Pagination in Django

Asynchronous JavaScript and XML (AJAX)

Understanding AJAX

AJAX stands for Asynchronous JavaScript and XML, which allows JavaScript to communicate asynchronously with the server using XML or JSON formats.

In synchronous communication, the client must wait for a server response before sending another request. Asynchronous communication allows multiple requests to be sent without waiting for previous responses.

Benefits include:

  • Partial page updates without full reloads
  • Dynamic content loading via JavaScript

jQuery Implementation of AJAX

$.ajax({
    url: '',
    type: 'POST',
    data: {'username': $(this).val()},
    success: function(data) {
        const result = JSON.parse(data);
        if (result['flag']) {
            $('p>span').removeClass('hide');
        }
    }
});

Server-side access:

request.POST or request.GET

Sending JSON Data with jQuery AJAX

$('#d1').click(function() {
    $.ajax({
        url: '',
        type: 'post',
        data: JSON.stringify({'name': 'jason', 'age': '18'}),
        contentType: 'application/json',
        success: function(data) {
            $('#i3').val(data);
        }
    });
});

Server-side access:

request.body  # Returns bytes

File Upload Using AJAX

Key considerations:

  1. Use new FormData()
  2. Access file input via $('#i1')[0].files[0]
  3. Set processData and contentType to false
  4. Retrieve files from request.FILES
  5. Regular key-value pairs can also be included in FormData
$("#btn").click(function() {
    var formdata = new FormData();
    formdata.append('name', $("#name").val());
    formdata.append('myfile', $("#myfile")[0].files[0]);
    
    $.ajax({
        url: '/index/',
        type: 'post',
        processData: false,
        contentType: false,
        data: formdata,
        success: function(data) {
            alert(data);
        }
    });
});

Backend handling:

def plus(request):
    if request.method == 'POST':
        print(request.FILES)
        file_obj = request.FILES.get('myfile')
        with open(file_obj.name, 'wb') as f:
            for chunk in file_obj:
                f.write(chunk)
        return HttpResponse('ok')
    return render(request, 'index.html')

Custom Pagination Class

Implementation of a custom pagination utility:

class Pagination(object):
    def __init__(self, current_page, all_count, per_page_num=2, pager_count=11):
        try:
            current_page = int(current_page)
        except Exception as e:
            current_page = 1

        if current_page < 1:
            current_page = 1

        self.current_page = current_page
        self.all_count = all_count
        self.per_page_num = per_page_num
        self.all_pager = int((all_count + per_page_num - 1) / per_page_num)
        self.pager_count = pager_count
        self.pager_count_half = int((pager_count - 1) / 2)

    @property
    def start(self):
        return (self.current_page - 1) * self.per_page_num

    @property
    def end(self):
        return self.current_page * self.per_page_num

    def page_html(self):
        if self.all_pager <= self.pager_count:
            pager_start = 1
            pager_end = self.all_pager + 1
        else:
            if self.current_page <= self.pager_count_half:
                pager_start = 1
                pager_end = self.pager_count + 1
            else:
                if (self.current_page + self.pager_count_half) > self.all_pager:
                    pager_end = self.all_pager + 1
                    pager_start = self.all_pager - self.pager_count + 1
                else:
                    pager_start = self.current_page - self.pager_count_half
                    pager_end = self.current_page + self.pager_count_half + 1

        page_html_list = []
        page_html_list.append('''
            <nav aria-label='Page navigation'>
            <ul class='pagination'>
        ''')

        first_page = '<li><a href="?page=%s">First Page</a></li>' % (1)
        page_html_list.append(first_page)

        if self.current_page <= 1:
            prev_page = '<li class="disabled"><a href="#">Pre Page</a></li>'
        else:
            prev_page = '<li><a href="?page=%s">Pre Page</a></li>' % (self.current_page - 1,)
        page_html_list.append(prev_page)

        for i in range(pager_start, pager_end):
            if i == self.current_page:
                temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i,)
            else:
                temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,)
            page_html_list.append(temp)

        if self.current_page >= self.all_pager:
            next_page = '<li class="disabled"><a href="#">Next Page</a></li>'
        else:
            next_page = '<li><a href="?page=%s">Next Page</a></li>' % (self.current_page + 1,)
        page_html_list.append(next_page)

        last_page = '<li><a href="?page=%s">Last Page</a></li>' % (self.all_pager,)
        page_html_list.append(last_page)

        page_html_list.append('''
            </nav>
            </ul>
        ''')
        return ''.join(page_html_list)

Usage in backend:

def publisher_list(request):
    current_page = int(request.GET.get('page'))
    total_count = models.Publisher.objects.count()
    page_obj = Pagination(current_page, total_count, request.path_info)
    data = models.Publisher.objects.all()[page_obj.start:page_obj.end]
    page_html = page_obj.page_html()
    return render(request, "publisher_list.html", {"publisher_list": data, "page_html": page_html})

Frontend rendering:

{{ page_html|safe }}

Tags: Django Ajax javascript Pagination web-development

Posted on Mon, 12 Oct 2026 16:18:10 +0000 by dcuellar