views:

241

answers:

4

Hi folks,

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.

e.g.

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

+4  A: 

Hi, 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.

Ross
+2  A: 

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.

Zack
Also, this method won't technically be non-blocking as Django is not a non-blocking framework in most deployments, but it will let you do something after returning a response. Tornado will let you perform non-blocking requests.
Zack
@Zack: thanks for that, I did not realize signals would help me with that.
RadiantHex
Don't forget to mark this as the answer if it works :)
Zack
-1. This does not do what the OP asked at all. Signals are executed in-process and will block the request while they run.
Daniel Roseman
As I said, Django does not offer a non-blocking callback of any kind, it does, however, give you the ability to perform processing after a request has been returned. I also gave a recommendation for a framework that *does* allow that, what more do you want?
Zack
@Zack: I'll it as soon as I can!
RadiantHex
But it's simply not true that using signals will allow you to do something after a request is returned. If you send a signal, that signal is executed then and there, in the same process. So the request won't be returned until the signal has finished executing.
Daniel Roseman
Please, re-read this until it becomes clearer, "Also, this method won't technically be non-blocking." You want a true, asynchronous, non-blocking callback? Tornado does that and much more. Signals basically do what RadiantHex asked: execute code after a Response is returned, but they block, like I said, and like I just reiterated.
Zack
+2  A: 

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.

RonaldHobbs
A: 

You could start a thread where you do your async work before you return from the function.

Here's a blog post about it http://www.chrisdpratt.com/2008/02/16/signals-in-django-stuff-thats-not-documented-well/

I just wonder if that has some side effects on some setups... It might also be bit too heavy on high traffic sites.

Epeli