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

Flo*_*ann 19 django http httpresponse django-middleware django-views

在我的Django应用程序中,我想跟踪响应是否已成功发送到客户端.我很清楚在像HTTP这样的无连接协议中没有"防水"方式来确保客户端已经接收(并显示)了响应,所以这不是关键任务功能,但我仍然希望在最新的可能时间.响应将不是HTML,因此任何来自客户端的回调(使用Javascript或IMG标签等)都是不可能的.

我能找到的"最新"钩子是在中间件列表的第一个位置添加一个实现process_response的自定义中间件,但根据我的理解,这是在构造实际响应并发送到客户端之前执行的.Django中是否有任何钩子/事件在响应成功发送后执行代码?

Flo*_*ann 21

我目前要使用的方法是使用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
Run Code Online (Sandbox Code Playgroud)

通过阅读Django代码,我非常确信HttpResponse.close()是将代码注入请求处理的最新点.我不确定与上述方法相比,这种方法是否确实存在更好的处理错误情况,所以我现在暂时搁置这个问题.

我更喜欢这种方法的原因是lazerscience的回答中提到的其他方法,它可以单独在视图中设置,不需要安装中间件.另一方面,使用request_finished信号将不允许我访问响应对象.

  • 适用于处理成功响应,但如果用户中断连接(通过关闭选项卡或点击"停止"按钮),则不执行close().如果在处理响应后需要执行某些操作,即使连接已被强制中断,也要定义\ __ del\___方法. (6认同)

Neu*_*onQ 8

如果您需要大量执行此操作,一个有用的技巧是拥有一个特殊的响应类,例如:

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

如果您想要快速/ hacky的“即发即弃”解决方案,而又无需费心集成适当的任务队列或从您的应用中分离出单独的微服务,则...将有帮助。

  • 本质上不是:P ...但是当您在代码中需要大量的“然后响应” -s并且您需要*每个人都做一些完全不同的事情*而不必创建单独的东西时,用这种方式编写会更优雅为他们上课-我想大多数尝试这样做的人都会像我一样在这种情况下结束。我更喜欢这种架构,我认为ppl应该看到更多的实现方式并选择他们喜欢的任何方式,我只是想将ppl推向功能编程/少类代码风格:) (4认同)