Я ищу способ выполнить код в Django после того, как ответ был отправлен клиенту. Я знаю, что обычный способ - реализовать очередь задач (например, Celery). Однако служба PaaS, которую я использую (PythonAnywhere), не поддерживает очереди задач по состоянию на май 2019 года. Она также кажется слишком сложной для нескольких простых случаев использования. Я нашел следующее решение на SO: Выполнить код в Django после отправки ответа клиенту. Принятый ответ отлично работает при локальном запуске. Однако в рабочей среде PythonAnywhere он по-прежнему блокирует отправку ответа клиенту. Что вызывает это?
Вот моя реализация:
from time import sleep
from datetime import datetime
from django.http import HttpResponse
class HttpResponseThen(HttpResponse):
"""
WARNING: THIS IS STILL BLOCKING THE PAGE LOAD ON PA
Implements HttpResponse with a callback i.e.,
The callback function runs after the http response.
"""
def __init__(self, data, then_callback=lambda: 'hello world', **kwargs):
super().__init__(data, **kwargs)
self.then_callback = then_callback
def close(self):
super().close()
return_value = self.then_callback()
print(f"Callback return value: {return_value}")
def my_callback_function():
sleep(20)
print('This should print 20 seconds AFTER the page loads.')
print('On PA, the page actually takes 20 seconds to load')
def test_view(request):
return HttpResponseThen("Timestamp: "+str(datetime.now()),
then_callback=my_callback_function) # This is still blocking on PA
Я ожидаю, что ответ будет отправлен клиенту немедленно, но на самом деле загрузка страницы занимает целых 20 секунд. (На моем ноутбуке код работает отлично. Ответ отправляется немедленно, а операторы печати выполняются через 20 секунд.)
close()
выдает сигналrequest_finished
. Пробовали ли вы слушать этот сигнал и действовать в соответствии с ним? - person nik_m   schedule 18.05.2019close()
для отправки ответа клиенту до выполнения функции обратного вызова. (На самом деле я хочу, чтобы request_finished выполнил сигнал после ответа клиенту. К сожалению, я проверил это, и это не так, как это реализовано в исходном коде.) - person pandichef   schedule 18.05.2019def my_request_finished_function(sender, environ, **kwargs): sleep(60)
. Запрос просто зависнет на 60 секунд. Напротив, я хочу, чтобы ответ был отправлен, а затем был запущен дополнительный код. - person pandichef   schedule 18.05.2019