btv2bt
V2EX  ›  Django

Django view 怎样可以先返回结果,再执行一部分其他逻辑?

By btv2bt at 2020 年 2 月 28 日 · 5617 次点击

除去 Celery 的话,还有其他的办法么?

第 1 条附言  ·  2020 年 2 月 28 日
具体场景:
Windows 环境,API 接收到请求之后(随后告诉请求方参数已收到),根据参数执行一段 cmd 命令,命令执行完后再把结果返回给请求方
第 2 条附言  ·  2020 年 2 月 28 日
似乎描述的不太清楚,思路是比较明确的,像站长说的那样;

只是不确定用哪种具体的 库 /方法 来实现
第 3 条附言  ·  2020 年 2 月 28 日
现在方案是站长说的那种,再具体些就是:

A 发请求到 B 的某个 API,
B 收到后返回 任务 id,
B 执行任务,
结果返回至 A 的结果收集接口


此处请教的是如何实现 先返回 id,再执行后续逻辑;
起初描述的是先返回结果,可能造成了一部分疑问
32 条回复  •  2020-06-27 01:18:36 +08:00
iConnect
   1
iConnect  
   2020 年 2 月 28 日 via Android
async 在一个线程里可以,thread 也可以在多个线程里
btv2bt
   2
btv2bt  
OP
   2020 年 2 月 28 日
@iConnect 不是很明白,方便细说一下么
Livid
   3
Livid  
MOD
PRO
   2020 年 2 月 28 日
如果你可以说一下具体的应用场景,然后可能会有其他解决方法。
qile1
   4
qile1  
   2020 年 2 月 28 日 via Android
楼主是不是想,直接返回保存成功,另一个线程后台保存数据到数据库?
btv2bt
   5
btv2bt  
OP
   2020 年 2 月 28 日
@Livid Windows 环境,API 接收到请求之后(随后告诉请求方参数已收到),根据参数执行一段 cmd 命令,命令执行完后再把结果返回给请求方
btv2bt
   6
btv2bt  
OP
   2020 年 2 月 28 日
@qile1 嗯,类似,具体可以看上一条回复
woodensail
   7
woodensail  
   2020 年 2 月 28 日
感觉是类似长连接的需求啊,这种做法服务端和客户端都得改造,代价太大了。
改用离线计算的方式来实现?
Livid
   8
Livid  
MOD
PRO
   2020 年 2 月 28 日   ❤️ 1
那么你可能需要这样来实现它:

API 收到请求之后,返回一个任务 ID,然后用异步任务去执行,执行完毕之后根据分配的任务 ID 写入结果。

请求方根据任务 ID 发起另外一个或者多个请求去拿结果,在异步任务没有完成之前会拿到「任务还没有执行完毕」,完成之后拿到的就是异步任务写入的结果。
cominghome
   9
cominghome  
   2020 年 2 月 28 日
站长的方式靠谱。典型的异步任务流程。
btv2bt
   10
btv2bt  
OP
   2020 年 2 月 28 日
@woodensail 离线计算怎么讲;
的确类似长链接,现在还没开始写…所以也还好,不知道有啥建议么

说到这,想起感觉可以中间用个 redis 之类的来处理下?
btv2bt
   11
btv2bt  
OP
   2020 年 2 月 28 日
@Livid
@cominghome en ,现在思路就是这样的
只是不知道用哪种具体的方式来实现 异步任务
woodensail
   12
woodensail  
   2020 年 2 月 28 日
站长给离线计算的方案了,另外就是注意离线计算结果的保存和销毁策略。可以考虑比如定时 1 小时销毁;或者按账号,每个账号只保留最新的一个计算结果。
Livid
   13
Livid  
MOD
PRO
   2020 年 2 月 28 日
不过貌似 Django 也考虑了这种情况,仅供参考吧:

https://stackoverflow.com/a/15569619
mimzy
   14
mimzy  
   2020 年 2 月 28 日
有类似场景,用了 Celery,前端轮询结果,感觉轮询这里不太优雅
fengshils
   15
fengshils  
   2020 年 2 月 28 日
使用 celery 返回任务 id,在定时去拿结果可好
est
   16
est  
   2020 年 2 月 28 日
具体是可以不用其他库实现的。

但是 LZ 说这个需求不对。你要的是浏览器配合。
676529483
   17
676529483  
   2020 年 2 月 28 日
一般都用 celery 做吧,如果用最新的 django3.0,可以考虑下 django_simple_backend 这个库
btv2bt
   18
btv2bt  
OP
   2020 年 2 月 28 日
@mimzy 结果回写到 db,结果查询请求单独写个接口更合适些

@fengshils
btv2bt
   19
btv2bt  
OP
   2020 年 2 月 28 日
@676529483 嗯,只是不太想在 Windows 上折腾 celery😂

服务器这边用了 celery 4,客户端这边 windows 又不支持 4,就有点蛋疼
wuwukai007
   20
wuwukai007  
   2020 年 2 月 28 日 via Android
别用 celery 在 windows 上,用了还要在配个 redis,徒增成本
btv2bt
   21
btv2bt  
OP
   2020 年 2 月 28 日
@wuwukai007 是的啊,所以想问有没其他办法…

是不是换 tornado 就好了……
wuwukai007
   22
wuwukai007  
   2020 年 2 月 28 日 via Android
曲线一点,用 apscheduler 做异步任务,建张状态表,直接返回前端任务启动成功与否,然后任务里面写状态,前端 api 访问状态,完成后在查表返回结果
xgq89757
   23
xgq89757  
   2020 年 2 月 28 日 via iPhone
@btv2bt django 的 5 大中间件不知道能不能满足你的需求。
btv2bt
   24
btv2bt  
OP
   2020 年 2 月 28 日
@xgq89757 提醒了我,谷歌了一下 django after response,有两种思路:
* 有一个第三方库
* 重载一个 HttpResponse

我试一下去,谢谢啦
robinlovemaggie
   25
robinlovemaggie  
   2020 年 2 月 28 日
参考各大话费充值系统和类银行转账系统的事务模型。
ytymf
   26
ytymf  
   2020 年 2 月 28 日
不想用 celery,还有 huey,不过也要 redis
xgq89757
   27
xgq89757  
   2020 年 2 月 29 日 via iPhone
@btv2bt 可以用 process_response 这个,django 自带的,执行视图函数结束之后会调用这个
btv2bt
   28
btv2bt  
OP
   2020 年 2 月 29 日 via Android
@xgq89757 我试了一下重构 response,但还是会阻塞,用了一个第三方库,没这个问题了;
process response 的话,会阻塞吗
bnm965321
   29
bnm965321  
   2020 年 3 月 12 日
重载 response 会堵塞,因为没有释放这个 server 不能继续接客
btv2bt
   30
btv2bt  
OP
   2020 年 3 月 13 日 via Android
@bnm965321 嗯,用了 after response 这个东西,看了下代码应该是有个单独的线程在处理队列里的东西
Vieufoux
   31
Vieufoux  
   2020 年 6 月 25 日
@btv2bt 所以楼主最后采用了哪种方案?
btv2bt
   32
btv2bt  
OP
   2020 年 6 月 27 日 via Android
@Vieufoux after response 这个第三方库
© 2026 V2EX · 44ms · 3.9.8.5