3

I am trying to make a web application based on Django that takes user input and performs Heavy background task that completes in almost five to ten minutes. When the background task is completed, few parameters are supplied to the template to render. Everything works fine and the page loads after that.

But when I am trying to use AJAX for this as it does'nt seems good that the page is loading for so long due to background heavy processing, I am not able to figure out how to reload the page (Though I am able to show an alert on completion but instead of this I want to re-render the page)

Here is my views.py code:

def index(request):
    #All Background process code goes here
    return render(request, 'form.html', {'scanResults' : scanResults, 'context_list' : context_list, 'scanSummary' : scanSummary})

Here is my AJAX call

<script type="text/javascript">
$(document).on('submit','#scanForm', function(e){
    e.preventDefault();
    $.ajax({
        type: 'POST',
        url: '/scanner/',
        data: {
            email: $('#email').val(),
            context: $('#context').val(),
            csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val(),
        },
        success:function(response){
            alert('Scan Completed');
            location.reload();
        }
    });
});

I am not able to figure out, what should I write in success function to reload the page that index function has returned to template.

My main motive is to show a progress bar that tells the progress of process in background (I have'nt implemented the code yet )and once the process is completed , refresh the page with response.

Thank You

Kunal
  • 59
  • 2
  • 4

1 Answers1

0

If you want to check the progress of a process you may need a polling mechanism as a solution.
This requires you to have a Model that has a state to determine if your scan is still in progress or has succeeded.

Since you will reload the page to display the results, you should have a logic in your index view to return a different template or context for when a user has yet to start scanning and when the scanning is successful.

from django.http import JsonResponse

def index(request):

    if status == 'success':
        # `status` may come from a Model which has a state .
        # If `status` is 'success' this means that your scanning has 
        # finished so you can have a different page or update context_list
        # based on success data.

    # Display input form
    form = scannerForm()

    return render(request, 'form.html', {
        'form': form,
        'context_list' : context_list,
        'scanSummary' : scanSummary
    })

You need a view to continuously check the scan status and returns a JSON response.

def scanner(request):
    #All Background process code goes here

    form = scannerForm(request.POST)
    status = form.perform_task()
    # During the task, your Model state should also be 
    # updated and return the status whether it is success, pending or failed etc..

    return JsonResponse({
        'status': status,
    })

Run the ajax poll to check the scanner view.

<script type="text/javascript">

$(document).on('submit','#scanForm', function(e){
  e.preventDefault();
  checkScanStatus();
});

function checkScanStatus () {
  $.ajax({
    type: 'POST',
    url: '/scanner/',
    data: {
      email: $('#email').val(),
      context: $('#context').val(),
      csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val(),
    },
    success: handleCheckScanStatus,
    error: handleScanError
  });
}


function handleCheckScanStatus (result) {
    if (result.status == 'success') {
      // Reload the page and display the condition you set for 'success' state
      // on the `index` view.
      location.reload();
    } else {
      // Show progress bar indicating that the process running in the background
      const interval = 5000; // Five seconds
      window.setTimeout(checkScanStatus, interval);
    }
}


function handleScanError (response) {
  console.error(response)
}
</script>

I would suggest to look into django celery for async tasks and django-fsm for transitioning model states.

If you just want a simple loader and do not need the check the specific status of your background task, you can use jQuery AJAX's beforeSend method to display a progress bar until the AJAX request finishes.

andrei1111
  • 454
  • 4
  • 6