V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
btv2bt
V2EX  ›  Django

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

  •  
  •   btv2bt · 2020-02-28 13:56:12 +08:00 · 4500 次点击
    这是一个创建于 1748 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

    只是不确定用哪种具体的 库 /方法 来实现
    第 3 条附言  ·  2020-02-28 14:59:23 +08:00
    现在方案是站长说的那种,再具体些就是:

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


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

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

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

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

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

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

    @fengshils
    btv2bt
        19
    btv2bt  
    OP
       2020-02-28 15:02:13 +08:00
    @676529483 嗯,只是不太想在 Windows 上折腾 celery😂

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

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

    我试一下去,谢谢啦
    robinlovemaggie
        25
    robinlovemaggie  
       2020-02-28 16:01:33 +08:00
    参考各大话费充值系统和类银行转账系统的事务模型。
    ytymf
        26
    ytymf  
       2020-02-28 16:50:05 +08:00
    不想用 celery,还有 huey,不过也要 redis
    xgq89757
        27
    xgq89757  
       2020-02-29 18:22:59 +08:00 via iPhone
    @btv2bt 可以用 process_response 这个,django 自带的,执行视图函数结束之后会调用这个
    btv2bt
        28
    btv2bt  
    OP
       2020-02-29 22:41:06 +08:00 via Android
    @xgq89757 我试了一下重构 response,但还是会阻塞,用了一个第三方库,没这个问题了;
    process response 的话,会阻塞吗
    bnm965321
        29
    bnm965321  
       2020-03-12 10:18:37 +08:00
    重载 response 会堵塞,因为没有释放这个 server 不能继续接客
    btv2bt
        30
    btv2bt  
    OP
       2020-03-13 08:04:43 +08:00 via Android
    @bnm965321 嗯,用了 after response 这个东西,看了下代码应该是有个单独的线程在处理队列里的东西
    Vieufoux
        31
    Vieufoux  
       2020-06-25 14:42:20 +08:00
    @btv2bt 所以楼主最后采用了哪种方案?
    btv2bt
        32
    btv2bt  
    OP
       2020-06-27 01:18:36 +08:00 via Android
    @Vieufoux after response 这个第三方库
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   883 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 20:00 · PVG 04:00 · LAX 12:00 · JFK 15:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.