Django可以做多线程的工作吗?

Rob*_*ert 26 django multithreading

我有一个问题,Django可以做多线程的工作吗?

这就是我想要做的:点击网页上的一个按钮,然后在model.py中有一些功能开始运行,例如,从互联网抓取一些数据,完成后,它会返回给用户结果.

我想我必须打开一个新的线程来执行model.py中的函数,有人能告诉我怎么做吗?非常感谢你.

cwa*_*ole 16

  1. 是的,它可以是多线程的,但通常一个人使用Celery来做同等的事情.您可以在celery-django教程中了解如何操作.
  2. 实际上想要强迫用户等待网站是很少见的.虽然它超过了超时的风险.

这是你所描述的一个例子.

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.
Run Code Online (Sandbox Code Playgroud)

更好的方法:

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 
Run Code Online (Sandbox Code Playgroud)

  • Celery有很多用途.请停止推荐它作为任何不需要阻止请求/响应的灵丹妙药.这就像每当有人询问如何存储一行文本时推荐RDBMS. (89认同)
  • (如果你有其他的建议,那么请把它们作为*答案*.我推荐了一些我过去见过的作品,它可能已经过时了,它可能是一个挂钩的战斗斧,但它碰巧工作了.我们拥有*这个网站的主要原因之一是人们可以提出替代答案而不仅仅是一次性评论. (21认同)
  • @andybak随意提出替代方案.对我来说,这听起来像是合法使用. (11认同)
  • 取决于细节,但你可以生成一个线程并轮询完成,你可以使用一个简单的cron作业来检查任务,或者如果你需要更多的功能,你可以使用几个"不像芹菜"项目中的一个例如huey或django-background-tasks. (5认同)
  • 芹菜在很多情况下太重了,不应该是涉及异步工作的请求的后备位置.如果一个异步事务要花掉一分钟的CPU时间,那很好,去Celery吧.当用户登录时,我想将某些用户数据提取到内存缓存,这样我就可以在导航系统时快速访问它.为此,芹菜很糟糕.但是,我不希望在缓存发生时阻止用户登录页面.Django非常适合某些事情,但是如果你依赖顺序的外部RPC(ORM,内存缓存等),它会不顾一切地放弃马桶上的循环/内存. (3认同)
  • 我的经验是,从工程角度来看,生成线程的成本更高。 (2认同)

nbw*_*ard 8

该答案所示,您可以使用线程包执行异步任务。每个人似乎都推荐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()
Run Code Online (Sandbox Code Playgroud)

您的前端可以发出startTask启动爬网的请求,也可以发出Ajax请求以对其进行检查,checkCrawl并在完成后返回true和结果。

  • 在线程完成之前,为服务 Web 请求而创建的进程不会运行吗? (2认同)
  • Django 团队在 v4.0 中引入了异步支持。这有关系吗?关于处理数据库时的 async_to_sync 等方法。[异步支持](https://docs.djangoproject.com/en/dev/topics/async/) (2认同)