在Django / Python中从头到尾跟踪单个请求

时间:2018-07-12 15:36:00

标签: python django

Django中是否存在一种从头到尾唯一地跟踪单个请求的方法?特别。我想知道BeforeViewMiddleware中的请求与ResponseMiddleware中的请求相同。

当前我使用request.session:

# executes at start of processing
class BeforeViewMiddleware(object):
    def process_view(self, request, view_func, view_args, view_kwargs):
        id = insert_data_into_table()
        request.session["id"] = id

# executes when all processing is done
class ResponseMiddleware(object):
    def process_response(self, request, view_func, view_args, view_kwargs):
        # Match the request with the request in BeforeViewMiddleware
        id = request.session["id"]
        update_table(id)

但是,如果大约在同一时间从同一会话发出两个或多个请求,则此操作将失败。然后,这变成了比赛条件,在该条件下,最先开始的比赛可能最后完成,并且ID混杂在一起。

2 个答案:

答案 0 :(得分:1)

为什么不对请求本身使用具体属性:

class BeforeViewMiddleware(object):
    def process_view(self, request, view_func, view_args, view_kwargs):
        id = ...
        request._unik_attr = id

class ResponseMiddleware(object):
    def process_response(self, request, view_func, view_args, view_kwargs):
        id = request._unik_attr
        # ...

与会话不同,请求对象仅在单个请求-响应-循环中存在。

答案 1 :(得分:0)

id的值存储在会话中是行不通的,因为您已经意识到,无论并发请求的数量如何,每个用户只有一个会话。

一种更好的方法是将数据存储在线程局部变量中。每个请求从头到尾都由同一个线程处理,因此数据始终保留在请求中。

from threading import local
_thread_data = local()

class BeforeViewMiddleware(object):
    def process_view(self, request, view_func, view_args, view_kwargs):
        _thread_data.my_id = insert_data_into_table()

class ResponseMiddleware(object):
    def process_response(self, request, view_func, view_args, view_kwargs):
        update_table(_thread_data.my_id)