【问题标题】:How to store data globally for a single request in Django?如何在Django中为单个请求全局存储数据?
【发布时间】:2020-05-01 23:50:51
【问题描述】:

我想为使用云计算(无状态!)的分布式请求准备我的 Django 网络服务。因此,我需要使我的请求完全模块化,并注意不使用来自先前请求的数据。 由于某些请求需要大量数据和函数,因此将这些数据传递给每个函数是不合理的。

问题:有哪些可能性可以为单个请求“全局”存储数据?

据我所知有两种可能,但似乎都不能满足我的需求:

1. Django 会话

在 request.session 中存储数据(使用中间件 'django.contrib.sessions.middleware.SessionMiddleware')。

当我理解正确时,数据仍然保留在同一用户的下一个请求之后,直到用户注销。

这对吗?

在我的测试中,每个新请求的数据都是空的。但我不明白为什么。 而且我仍然没有处理我所有函数中的请求。

有关 Django 会话的更多信息,请参阅:

2。 Python 全局关键字

将数据存储在 python 全局变量中。

这些数据独立于 Django 请求和会话存储。

有关全局变量的更多信息,请参阅:

解决方法

作为这两种解决方案的一个丑陋的解决方法,我可以在每个请求结束时删除“全局”数据,以保持每个请求独立于其他请求。

有没有更好的方法?

这种情况在 Django 中是什么意思?

提前感谢您的支持。

【问题讨论】:

    标签: python django session request


    【解决方案1】:

    这可能不是一个非常有效的解决方案,但您可以将其存储在线程空间中。

    我用它来为每个请求添加一个唯一 ID - request_id 并将其添加到记录器格式中。这样我就不必将request_id 传递给每个函数。

    我的中间件的init.py:

    import threading
    local = threading.local()
    

    这是我的自定义中间件:

    import json
    import uuid
    import traceback
    from django.utils.deprecation import MiddlewareMixin
    class RequestIDMiddleware(MiddlewareMixin):
        def process_request(self, request):
            de_run_id = str(uuid.uuid4())
            local.de_run_id = de_run_id
            request.de_run_id = de_run_id
            if request.body:
                try:
                    req = json.loads(request.body)
                    if req.get("app_id"):
                        local.app_id = req["app_id"]
                    elif req.get("APP_DATA", {}).get("metadata", {}).get("app_id"):
                        local.app_id = req["APP_DATA"]["metadata"]["app_id"]
                    else:
                        local.app_id = None
                except Exception, e:
                    local.app_id = None
            else:
                local.app_id = None
    

    这是我的自定义日志过滤器:

    import logging
    from xxxx.middleware import local
    
    
    class RequestIDFilter(logging.Filter):
        def filter(self, record):
            record.de_run_id = getattr(local, 'de_run_id')
            record.app_id = getattr(local, "app_id")
            return True
    

    您可以在项目的 init.py 中定义本地。然后用中间件(或任何你觉得合适的东西)覆盖它,并在整个项目中访问local

    这是否是最适合您的解决方案取决于here 讨论的很多因素

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多