0

(Using Django) I'm creating a web application, this is how it's supposed to work :

  1. From the webpage - User selects an option, clicks on it
  2. The URL hits the associated view
  3. Inside the view function, another python module function start processing - which takes a while (could be 5 mins or 2 hours)
  4. The function execution logging is visible on the webpage as it happens - real time execution is visible on the webpage itself (asynchronously)

I found that, this can be achieved using AJAX. And I tried something like this:

views.py:

from lib.testnew import testprint

def printtest(request):
    if 'create_btn' in request.POST:
        test = testprint()
        data = test.printing()
        logger.info(data)
        return render(request, 'create.html', {'data': data})
    else:
        logger.info("initiating")
        return render(request, 'createvm.html')

create.html

{% extends 'base.html' %}

{% block content %}

<script type="text/javascript">
    $(document).ready(function(){

        $('#create_vm_btn').click(function(){
            $.ajax({
                type: "POST",
                url: "printtest",

                success: function(data) {
                  $("#output_id").html(data);
                  alert('Done: ' + data);
                }

            });
        });
    });

</script>
<h2>Welcome {{ user.first_name }} {{ user.last_name }}</h2>
<form method="post">
    <textarea id="output" row=3 cols=25></textarea>
    <button type="submit" class="btn btn-default" name="create_btn" id="create_btn">Create</button>
</form>
<script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>
{% endblock %}

The below line takes time to execute :

data = test.printing()

But it doesn't seem to have worked as I've explained in the points. Kindly suggest the right way.

2
  • But it doesn't seem to have worked as I want it to. and why you think we know how do you want? Commented Jun 7, 2018 at 11:50
  • @brunodesthuilliers I believe that I have explained my question in the points, if you don't think it's not easy to understand please let me know. Commented Jun 7, 2018 at 12:39

1 Answer 1

2

If I understand correctly, you want the first call to start the "processing" and subsequent calls to display progress. Bad news, it's not going to be that simple, for the obvious reason that calling the "processing" function from within the view will block until the "processing" function returns.

The solution here is to use an async task queue (Celery being the canonical solution - there are lighter ones but Celery makes it easier to scale your infra by adding new "processing" servers as needed), with one first view launching the processing task and returning a task id and a second view (which you can poll using ajax) checking the task progress (or you can go with django-channels if you want to get fancy but I suggest you start by making the thing works with just a plain ajax poll first).

Also, getting the "progress" from a log file is certainly not the easiest solution. What we're doing here is to have the celery tasks store progress info in Redis (which we already use as celery result backend) and the "poll" view read them back. Note that you can of course write your own logging.handler to do this (well, at least the "store it in Redis" part) if the log messages are what you want as "progress infos".

Sign up to request clarification or add additional context in comments.

2 Comments

I only want one call, upon that the script execution starts (within view function) and a console window will be activated on the webpage to display the output.
@Ayush sorry but this is just not how it works (please re-read my answer) - if you don't understand why then it might be time to learn about the HTTP request/response cycle and how django (or any similar framework / techno like flask, Rails, Symfony etc) handle a request/response cycle.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.