How to get django to give an HTTP response before continuing with the task associated with the request?

In my django piston API, I want to give / return an HTTP response to the client before calling another function, which will take quite a while. How to make the income give an HTTP response containing the desired JSON, and not a line related to the creation of the generator object?

My piston handler method looks like this:

def create(self, request): data = request.data *other operations......................* incident.save() response = rc.CREATED response.content = {"id":str(incident.id)} yield response manage_incident(incident) 

Instead of the answer I want, for example:

  {"id":"13"} 

The client receives the following line:

  "<generator object create at 0x102c50050>" 

EDIT:

I understand that using the lesson was the wrong way to do this, in fact, I am trying to ensure that the client immediately receives a response before the server switches to the expensive manage_incident () function

+6
source share
3 answers

This has nothing to do with generators or inferior ones, but I used the following code and decorator so that something would run in the background, immediately returning an HTTP response to the client.

Using:

 @postpone def long_process(): do things... def some_view(request): long_process() return HttpResponse(...) 

And here is the code to make it work:

 import atexit import Queue import threading from django.core.mail import mail_admins def _worker(): while True: func, args, kwargs = _queue.get() try: func(*args, **kwargs) except: import traceback details = traceback.format_exc() mail_admins('Background process exception', details) finally: _queue.task_done() # so we can join at exit def postpone(func): def decorator(*args, **kwargs): _queue.put((func, args, kwargs)) return decorator _queue = Queue.Queue() _thread = threading.Thread(target=_worker) _thread.daemon = True _thread.start() def _cleanup(): _queue.join() # so we don't exit too soon atexit.register(_cleanup) 
+7
source

Perhaps you could do something like this (be careful):

 import threading def create(self, request): data = request.data # do stuff... t = threading.Thread(target=manage_incident, args=(incident,)) t.setDaemon(True) t.start() return response 

Has anyone tried this? It is safe? I assume this is not the case, mainly due to concurrency issues, but also because if you get a lot of requests, you can also get many processes (as they may work for a while), but it may be worth it Togo.

Otherwise, you can simply add an incident that needs to be processed into your database and process it later through a cron job or something like that.

I don’t think Django is built for either concurrency or very time-consuming operations.

Edit

Someone tried seems to work.

+2
source

You turned your view into a generator, thinking that Django would pick this fact up and process it accordingly. Well, that won't be.

 def create(self, request): return HttpResponse(real_create(request)) 

EDIT:

Since you seem to be having problems ... visualizing this ...

 def stuff(): print 1 yield 'foo' print 2 for i in stuff(): print i 

exit:

 1 foo 2 
0
source

Source: https://habr.com/ru/post/892254/


All Articles