Может ли Django делать многопоточные работы?
У меня вопрос, может ли Django делать многопоточные работы?
Вот что я хочу сделать: нажмите кнопку на веб-странице, затем некоторые функции в model.py запускаются, например, сканируют некоторые данные из Интернета, когда они закончены, они возвращают пользователю результаты,
Интересно, что мне нужно открыть новый поток для выполнения функций в model.py, может ли кто-нибудь сказать мне, как это сделать? Большое вам спасибо.
Ответы
Ответ 1
Вот пример того, что вы описываете.
User sends request
Django receives => spawns a thread to do something else.
main thread finishes && other thread finishes
... (later upon completion of both tasks)
response is sent to user as a package.
Лучший способ:
User sends request
Django receives => lets Celery know "hey! do this!"
main thread finishes
response is sent to user
...(later)
user receives balance of transaction
Ответ 2
Как показано в этом ответе, вы можете использовать пакет потоков для выполнения асинхронной задачи. Кажется, что каждый рекомендует Celery, но он часто излишний для выполнения простых, но длительных задач. Я думаю, что на самом деле проще и прозрачнее использовать многопоточность.
Вот простой пример асинхронизации сканера:
#views.py
import threading
from .models import Crawl
def startCrawl(request):
task = Crawl()
task.save()
t = threading.Thread(target=doCrawl,args=[task.id])
t.setDaemon(True)
t.start()
return JsonResponse({'id':task.id})
def checkCrawl(request,id):
task = Crawl.objects.get(pk=id)
return JsonResponse({'is_done':task.is_done, result:task.result})
def doCrawl(id):
task = Crawl.objects.get(pk=id)
# Do crawling, etc.
task.result = result
task.is_done = True
task.save()
Ваш интерфейс может сделать запрос для startTask
, чтобы начать сканирование, он может сделать запрос Ajax, чтобы проверить его с помощью checkCrawl
, который вернет true и результат, когда он закончится.
Ответ 3
Если вы не хотите добавлять в свой проект какую-либо инфраструктуру для избыточного использования, вы можете просто использовать subprocess.Popen:
def my_command(request):
command = '/my/command/to/run' # Can even be 'python manage.py somecommand'
subprocess.Popen(command, shell=True)
command = '/other/command/to/run'
subprocess.Popen(command, shell=True)
return HttpResponse(status=204)
[править] Как уже упоминалось в комментариях, это не запустит фоновую задачу и сразу вернет HttpResponse. Он выполнит обе команды параллельно, а затем вернет HttpResponse после завершения обеих команд.