Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django - flush response?

Tags:

python

django

I am sending an AJAX request to a Django view that can potentially take a lot of time. It goes through some well-defined steps, however, so I would like to print status indicators to the user letting it know when it is finished doing a certain thing and has moved on to the next.

If I was using PHP it might look like this, using the flush function:

do_something();
print 'Done doing something!';
flush();

do_something_else();
print 'Done doing something else!';
flush();

How would I go about doing the same with Django? Looking at the documentation I see that HttpResponse objects have a flush method, but all it has to say is that "This method makes an HttpResponse instance a file-like object." - I'm not sure that's what I want. I'm having a hard time wrapping my head around how this could be done in Django since I have to return the response and don't really have a control of when the content goes to the browser.

like image 660
Paolo Bergantino Avatar asked Sep 03 '09 01:09

Paolo Bergantino


2 Answers

Most webservers (eg. FCGI/SCGI) do their own buffering, HTTP clients do their own, and so on. It's very difficult to actually get data flushed out in this way and for the client to actually receive it, because it's not a typical operation.

The closest to what you're trying to do would be to pass an iterator to HttpResponse, and to do the work in a generator; something like this:

def index(request):
    def do_work():
        step_1()
        yield "step 1 complete"
        step_2()
        yield "step 2 complete"
        step_3()
        yield "step 3 complete"
    return HttpResponse(do_work())

... but this won't necessarily flush. (Not tested code, but you get the idea; see http://docs.djangoproject.com/en/dev/ref/request-response/#passing-iterators.)

Most of the infrastructure is simply not expecting a piecemeal response. Even if Django isn't buffering, your front-end server might be, and the client probably is, too. That's why most things use pull updates for this: a separate interface to query the status of a long-running request.

(I'd like to be able to do reliable push updates for this sort of thing, too...)

like image 200
Glenn Maynard Avatar answered Oct 04 '22 00:10

Glenn Maynard


I'm not sure you need to use the flush() function.

Your AJAX request should just go to a django view.

If your steps can be broken down, keep it simple and create a view for each step. That way one one process completes you can update the user and start the next request via AJAX.

views.py

def do_something(request):
    # stuff here
    return HttpResponse()

def do_something_else(request):
    # more stuff
    return HttpResponse()
like image 29
monkut Avatar answered Oct 04 '22 01:10

monkut