代码之家  ›  专栏  ›  技术社区  ›  Florian Ledermann

将响应发送到客户端后在Django中执行代码

  •  16
  • Florian Ledermann  · 技术社区  · 14 年前

    在我的Django应用程序中,我希望跟踪是否已成功地将响应发送到客户机。我很清楚,在像HTTP这样的无连接协议中,没有“防水”的方式来确保客户机已经收到(并显示)响应,因此这将不是任务关键功能,但我仍然希望在最迟可能的时间完成这项工作。响应将不是HTML,因此无法从客户端(使用javascript或img标记等)进行任何回调。

    我能找到的“最新”钩子是在中间件列表的第一个位置添加一个实现过程响应的定制中间件,但据我所知,这是在构建实际响应并将其发送到客户机之前执行的。Django中是否有挂接/事件在成功发送响应后执行代码?

    3 回复  |  直到 6 年前
        1
  •  19
  •   Florian Ledermann    14 年前

    我现在要使用的方法使用httpResponse的子类:

    from django.template import loader
    from django.http import HttpResponse
    
    # use custom response class to override HttpResponse.close()
    class LogSuccessResponse(HttpResponse):
    
        def close(self):
            super(LogSuccessResponse, self).close()
            # do whatever you want, this is the last codepoint in request handling
            if self.status_code == 200:
                print('HttpResponse successful: %s' % self.status_code)
    
    # this would be the view definition
    def logging_view(request):
        response = LogSuccessResponse('Hello World', mimetype='text/plain')
        return response
    

    通过阅读django代码,我非常确信httpresponse.close()是将代码注入请求处理的最新点。我不确定与上面提到的方法相比,这种方法是否真的能更好地处理错误案例,所以我现在就把这个问题留到一边。

    与Lazerscience的答案中提到的其他方法相比,我更喜欢这种方法的原因是它可以单独在视图中设置,并且不需要安装中间件。另一方面,使用请求完成信号将不允许我访问响应对象。

        2
  •  1
  •   Bernhard Vallant    14 年前

    我想当你谈论中间件时,你是在考虑中间件的 process_request 方法,但还有一个 process_response method HttpResponse 返回对象。我想这是你能找到一个可以用的钩子的最新时刻。

    此外,还有一个 request_finished signal 被解雇。

        3
  •  1
  •   NeuronQ    6 年前

    如果您需要经常这样做,一个有用的技巧是有一个特殊的响应类,比如:

    class ResponseThen(Response):
        def __init__(self, data, then_callback, **kwargs):
            super().__init__(data, **kwargs)
            self.then_callback = then_callback
    
        def close(self):
            super().close()
            self.then_callback()
    
    def some_view(request):
        # ...code to run before response is returned to client
    
        def do_after():
            # ...code to run *after* response is returned to client
    
        return ResponseThen(some_data, do_after, status=status.HTTP_200_OK)
    

    …如果你想要一个快速/黑客式的“失火忘记”解决方案,而不必费心集成一个合适的任务队列,或者从你的应用程序中分离出一个单独的微服务,那么它会很有帮助。