在我的Django应用程序中,我想跟踪响应是否已成功发送到客户端。我很清楚在像HTTP这样的无连接协议中没有“防水”方式来确保客户端已经接收(并显示)了响应,所以这不是关键任务功能,但我仍然希望在最新的可能时间。响应将不是HTML,因此无法从客户端回调(使用Javascript或IMG标签等)。
我能找到的“最新”钩子是在中间件列表的第一个位置添加一个实现process_response的自定义中间件,但据我了解,这是在构建实际响应并发送到客户端之前执行的。 Django中是否有任何钩子/事件在成功发送响应后执行代码?
答案 0 :(得分:19)
我目前要使用的方法是使用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答案中提到的其他方法,它可以单独在视图中设置,不需要安装中间件。另一方面,使用request_finished信号将不允许我访问响应对象。
答案 1 :(得分:1)
我想在谈论中间件时,您正在考虑中间件的process_request
方法,但是当返回HttpResponse
对象时,还会调用process_response
method。我想这将是你可以找到一个可以使用的钩子的最新时刻。
此外还有request_finished
signal被解雇。
答案 2 :(得分:1)
如果您需要做很多事情,一个有用的技巧是拥有一个特殊的响应类,例如:
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)
...如果您想要一种快速/灵活的“即发即忘”解决方案,而又无需费心集成适当的任务队列或从应用中分离出单独的微服务,则将为您提供帮助。