Django post_保存信号是否异步?

Django post_保存信号是否异步?,django,signals,Django,Signals,我有一个like功能,就像社交网络like或拇指竖起功能一样;用户点击star/heart/which来标记喜欢的内容。这是用ajax完成的,必须很快 这里唯一的问题是,出于某些原因,我必须为每个like执行一些任务,我发现它们是在like视图中直接编码的,这会使速度变慢 我正在考虑使用信号使这些任务的执行异步,以便视图可以立即将json发送回javascript,而无需等待任务完成 我开始为像这样的创建一个信号,但后来意识到Django的信号不是异步的,它最终也会是一样的,视图必须等待信号完成

我有一个
like
功能,就像社交网络like或拇指竖起功能一样;用户点击star/heart/which来标记喜欢的内容。这是用ajax完成的,必须很快

这里唯一的问题是,出于某些原因,我必须为每个
like
执行一些任务,我发现它们是在
like
视图中直接编码的,这会使速度变慢

我正在考虑使用信号使这些任务的执行异步,以便视图可以立即将
json
发送回
javascript
,而无需等待任务完成

我开始为像这样的
创建一个信号,但后来意识到Django的
信号
不是异步的,它最终也会是一样的,视图必须等待信号完成才能发回响应


因此,我可以尝试使
信号
异步,正如这里和那里所解释的那样,但我也可以将
post_save
信号用于
like
模型,但现在我想知道视图是否可以在执行信号之前完成?

嗯,首先,Django中的信号不是异步的。对于您的特殊情况,我认为
post\u save
是错误的做法。最直接的方法是简单地触发一个ajax请求,查看您喜欢的操作,而不等待响应。而是在触发请求后直接修改视图/html


当然,这需要您事先知道允许您的用户喜欢此项目,并且您的请求不会失败。

您需要的是一个线程。它们很容易使用。您只需子类化
threading.Thread
并编写
run
方法:

import threading

class LikeThread(threading.Thread):
    def __init__(self, user, liked, **kwargs):
        self.user = user
        self.liked = liked
        super(LikeThread, self).__init__(**kwargs)

    def run(self):
        # long running code here
然后,当您准备好执行任务时,您可以通过以下方式启动它:

LikeThread(request.user, something).start()
视图代码的其余部分或任何内容将继续并返回响应,线程将愉快地完成其工作,直到完成,然后自行结束


请参阅完整文档:

还可以查看(或更具体地说)。它是一个异步任务调度程序/处理程序。因此,您的post_save信号处理程序创建一个任务,该任务通过芹菜拾取并执行。这样,即使在不同的机器或一批机器上,也可以异步执行繁重的工作,但您仍然可以获得快速的应用程序。

async signals
package()对这个问题进行了抽象。调用异步信号函数;如果芹菜是目前的包使用它发出信号异步从一个工人;如果没有芹菜,包装会以传统的同步方式发送信号。

这很有趣;但我的印象是python下的线程受到GIL的限制?当然,是这样。如果你不想变异任何东西,这不是问题。如果您只是发送一封包含数据的电子邮件,等等。如果您需要实际修改任何内容,并且可能存在潜在的线程安全问题,那么您需要明智地使用锁。尽管如此,如果你需要卸载一个长时间运行的进程,你真的没有选择。那么使用更昂贵的多处理呢?多处理只是类固醇上的线程。您可以使用它,但除非您正在运行的代码需要多个核心来处理(提示:您需要对大型数据集和此类或极端图形密集型的工作进行严肃的科学处理),否则使用多处理是浪费时间。我理解这是一个较老的问题/答案,但我相信目前芹菜应该是公认的答案(正如我在芹菜答案中所说的)。在代码库中引入多线程可能会带来很多问题。芹菜是专门为解决OP的问题而设计的。我不太喜欢假设会发生什么,这对我来说是个肮脏的把戏;)克里斯的回答让我更加信服。在我看来,使用线程也是一样的。您将生成线程,在前端继续处理,并且不知道该线程是否将失败或成功。在Django中使用线程是我的一部分,但最终这并不是一个好主意(从调试的角度来看,从资源角度来看,等等)。如果情况不好,那么系统中就会有很多僵尸线程。如果您想要异步行为,请使用西芹之类的任务处理程序。另一个选择是使用gevent或类似产品的绿色螺纹,价格较低。这确实很有道理。在我的例子中,如果线程失败,那就没那么糟糕了。我想在这里把那些需要快速确认的任务与那些可能会占用更多时间并且默默失败的任务分离开来。使用threads解决方案,我不必在检查是否允许用户喜欢时妥协,我还可以向javascript发回确认,并假设它不起作用。然后,其他任务,如发送电子邮件和其他通知,应该没有理由失败,但我会按照你的建议,并检查芹菜和类似的。直接回答:不。这是同步。我相信这应该是现在接受的答案!我总是建议不要在代码库中引入多线程,如果有其他选择,Chris发布的代码确实显示了
easy
冰山一角,但没有提到引入多线程时可能出现的所有问题。