Запуск длительного процесса в представлении Django

У меня есть представление (start_job_view) в Django, которое должно запускать очень длинный процесс. Я хотел бы, чтобы представление немедленно возвращалось и добавляло сообщение пользователю ("ваша работа началась", используя фреймворк сообщений), и я хотел бы, чтобы при завершении длительного процесса оно отправляло новое сообщение пользователю ("ваша работа закончилась").

Как я могу это сделать?

Примечание: Я не хочу добавлять Celery в свой проект только для этой задачи...

Одним из вариантов является использование представления async. Более подробную информацию вы можете получить здесь

Другим способом может быть создание задачи celery и вызов ее в вашем представлении.

Вы можете использовать очередь in-memory, которая работает в отдельном потоке. Посмотрите на код библиотеки сегмента, который объединяет/обрабатывает события в потоке bg здесь.

Обратите внимание, что в случае, если ваш сервер будет остановлен по какой-либо причине, у вас есть механизм для определения неудачного задания и повторной попытки.

Предполагается, что у вас запущено несколько экземпляров сервера Django, которые подключаются к выделенному серверу БД. Я бы просто использовал таблицу базы данных в качестве "очереди" для хранения задач, которые необходимо выполнить.

Затем используйте systemd для запуска команды Django в качестве рабочих задач на одном или нескольких экземплярах сервера. Когда рабочий простаивает, он может запросить таблицу для следующей задачи.

Введите колонку "статус", чтобы пометить задачу как выполненную. Тогда ваш Django frontend сможет проверить наличие доступных "выполненных" задач, добавить сообщение на возвращаемую страницу и удалить задачу из таблицы.

в views.py

def your_view(self, request):
   # your code          
   t = BackgroundTasksUtils(user) # Not required to pass parameter (it's up to you)
   t.start()
   return something

в bg_task.py

import threading

class BackgroundTasksUtils(threading.Thread):
   def __init__(self, user):
       super(BackgroundTasksUtils, self).__init__()
       self.user = user
   def run(self):
       # your code that taking too much time (in my case sending mail to user) 
   def __str__(self):
       return something

если вы не указываете никаких параметров в views.py, то не забудьте удалить __init__ в bg_task.py

Для лучшего и более глубокого понимания посетите threading

Вернуться на верх