Подтвердить что ты не робот

Может ли Django делать многопоточные работы?

У меня вопрос, может ли Django делать многопоточные работы?

Вот что я хочу сделать: нажмите кнопку на веб-странице, затем некоторые функции в model.py запускаются, например, сканируют некоторые данные из Интернета, когда они закончены, они возвращают пользователю результаты,

Интересно, что мне нужно открыть новый поток для выполнения функций в model.py, может ли кто-нибудь сказать мне, как это сделать? Большое вам спасибо.

4b9b3361

Ответ 1

  • Да, он может многопоточно, но, как правило, он использует Celery для выполнения эквивалента. Вы можете прочитать о том, как в учебнике celery-django.
  • Редко, что вы действительно хотите заставить пользователя ждать веб-сайта. Хотя это лучше, чем риски таймаута.

Вот пример того, что вы описываете.

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 после завершения обеих команд.