简体   繁体   中英

Performing non-blocking requests? - Django

I have been playing with other frameworks, such as NodeJS, lately.

I love the possibility to return a response, and still being able to do further operations.

eg

def view(request):
  do_something()
  return HttpResponse()

  do_more_stuff() #not possible!!!

Maybe Django already offers a way to perform operations after returning a request, if that is the case that would be great.


Help would be very much appreciated! =D

not out of the box as you've already returned out of the method. You could use something like Celery which would pass the do_more_stuff task onto a queue and then have it run do_more_stuff() outside of http request / response flow.

Django lets you accomplish this with Signals, more information can be found here . (Please note, as I said in comments below, signals aren't non-blocking, but they do allow you to execute code after returning a response in a view.)

If you're looking into doing many, many asynchronous requests and need them to be non-blocking, you may want to check out Tornado .

Because you're returning from the function, do_more_stuff will never be called.

If you're looking at doing heavy lifting stuff queuing up something before you return as Ross suggests (+1 for Celery).

if however you're looking at returning some content... then doing something and returning more content to the user streaming is probably what you're looking for. You can pass an iterator or a generator to HttpResponse, and it'll iterate and push out the content in a trickle fashion. It feels a bit yuck, but if you're a generator rockstar you may be able to do enough in various states to accomplish what you want.

Or I guess you could simply redesign your page to use a lot of ajax to do what you need, including firing off events to django views, reading data from views, etc.

It kind of comes down to where the burden of async is going to sit: client, server or response.

I'm not that familiar with node.js yet, but it would be interesting to see the use case you're talking about.

EDIT: I did a little more looking into signals, and while they do occur in process, there is a built in signal for request_finished after the request has been handled by django, though it's more of a catchall than something specific.

You can use threading as a temporary fix or as a non-production solution but it is neither scalable nor the best practice. Use celery for better design!

def foo(request):
    import threading
    from time import sleep
    def foo():
        sleep(5)
        # Do something
        print('hello, world')
    threading.Thread(target=foo).start()
    return JsonResponse(data={'detail': 'thread started'})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM