Python 有没有办法从Django的任何地方访问上下文?

Python 有没有办法从Django的任何地方访问上下文?,python,django,Python,Django,我正在寻找一种方法,使django请求中的任何模块都可以访问全局变量,而无需将其作为参数传递。传统上,在其他MVC中,我会将其存储在请求上下文或会话中,并使用类似“get_current_context”的方法(在Django中找不到)访问上下文 是否有这样的机制,或者其他机制允许我在请求上下文中的任何位置都可以使用值 蒂亚 更新:我的研究只提出了一个可行的解决方案-线程局部性(有些人会说它不可行,但关于它的讨论相当活跃,有正反两方面,似乎大多数人认为如果你负责任地使用它,你应该能够在Djang

我正在寻找一种方法,使django请求中的任何模块都可以访问全局变量,而无需将其作为参数传递。传统上,在其他MVC中,我会将其存储在请求上下文或会话中,并使用类似“get_current_context”的方法(在Django中找不到)访问上下文

是否有这样的机制,或者其他机制允许我在请求上下文中的任何位置都可以使用值

蒂亚


更新:我的研究只提出了一个可行的解决方案-线程局部性(有些人会说它不可行,但关于它的讨论相当活跃,有正反两方面,似乎大多数人认为如果你负责任地使用它,你应该能够在Django中使用它)。

你必须编写自己的ContextProcessor,就像我解释的那样


编辑:

创建上下文处理器后,例如

def ip_address_processor(request):
  return {'ip_address': request.META['REMOTE_ADDR']}
您可以通过初始化RequestContext获得所需的变量,如下所示:

from django.template import RequestContext

def myview(request):
  rc = RequestContext(request)
  rc.get('ip_address')
但是,请注意,如果不将上下文处理器放在TEMPLATE_Context_PROCESSORS元组中,则必须将处理器作为参数传递给RequestContext,例如:

from django.template import RequestContext

def ip_address_processor(request):
  return {'ip_address': request.META['REMOTE_ADDR']}

def myview(request):
  rc = RequestContext(request, processors=[ip_address_processor])
  rc.get('ip_address')
一些有用的链接:


您仍然可以在几乎任何地方访问当前会话

使用:

这当然会使用数据库和会话表,因此开销可能有点太大。可变会话是特定的,还是只是一种全局成本

文件:


另外,我过去所做的是用列session_id和其他各种东西创建我自己的表,然后根据session_id手动执行SQL选择数据。比使用SessionStore()sugar要快得多,我仍然不完全清楚您想要实现什么,但听起来您可能需要以下内容

如果您在中创建一个中间件,比如

myproject/myapp/middleware/globalrequestmiddleware.py
…看起来像这样

import thread

class GlobalRequestMiddleware(object):
    _threadmap = {}

    @classmethod
    def get_current_request(cls):
        return cls._threadmap[thread.get_ident()]

    def process_request(self, request):
        self._threadmap[thread.get_ident()] = request

    def process_exception(self, request, exception):
        try:
            del self._threadmap[thread.get_ident()]
        except KeyError:
            pass

    def process_response(self, request, response):
        try:
            del self._threadmap[thread.get_ident()]
        except KeyError:
            pass
        return response
from myproject.myapp.middleware.globalrequestmiddleware import GlobalRequestMiddleware

# Get the current request object for this thread
request = GlobalRequestMiddleware.get_current_request()

# Access some of its attributes
print 'The current value of session variable "foo" is "%s"' % request.SESSION['foo']
print 'The current user is "%s"' % request.user.username

# Add something to it, which we can use later on
request.some_new_attr = 'some_new_value'
…然后将其作为列表中的第一项添加到
设置.py
中间件类中

MIDDLEWARE_CLASSES = (
    'myproject.myapp.middleware.globalrequestmiddleware.GlobalRequestMiddleware',
    # ...
)
…然后您可以在请求/响应过程中的任何位置使用它,就像这样

import thread

class GlobalRequestMiddleware(object):
    _threadmap = {}

    @classmethod
    def get_current_request(cls):
        return cls._threadmap[thread.get_ident()]

    def process_request(self, request):
        self._threadmap[thread.get_ident()] = request

    def process_exception(self, request, exception):
        try:
            del self._threadmap[thread.get_ident()]
        except KeyError:
            pass

    def process_response(self, request, response):
        try:
            del self._threadmap[thread.get_ident()]
        except KeyError:
            pass
        return response
from myproject.myapp.middleware.globalrequestmiddleware import GlobalRequestMiddleware

# Get the current request object for this thread
request = GlobalRequestMiddleware.get_current_request()

# Access some of its attributes
print 'The current value of session variable "foo" is "%s"' % request.SESSION['foo']
print 'The current user is "%s"' % request.user.username

# Add something to it, which we can use later on
request.some_new_attr = 'some_new_value'

…或您想做的任何事情。

也许吧,但请记住,每个请求可以有多个上下文,多个线程(=多个请求)并行运行,这可能会在任何时间点产生数百个活动上下文,因此它如何知道返回哪个上下文?我不确定是否理解您的问题。我说的是能够从代码中的任何地方访问类似会话的内容(而不必传递会话变量)。好的,“上下文”指的是
django.template.context
对象或其子类,您稍后将使用它来呈现
django.template.template
。如果是这样,如果您正在呈现多个
模板
对象(例如,如果您正在使用自定义模板标记),则每个请求可以有多个
上下文
对象。如果您使用的是Django内置的基于类的视图,如
TemplateView
,那么该过程的大部分内容都是隐藏的。这可能有助于用一个代码示例来阐明您想要实现的目标。我不确定这将如何允许我拥有一个可以从代码中任何地方(任何控制器、任何内部库等)访问的变量。在这个示例中,您实际上是在将请求作为参数传递,以获取上下文。这实际上是我试图避免的。到目前为止,使用线程局部变量似乎提供了这个问题的答案(尽管有些人声称不建议这样做),您的问题是关于“上下文”变量的,所以我提供了适当的答案。定义全局变量根本不是最好的主意,因此我建议您重新考虑应用程序设计,而不是继续前进。如果您需要一些常量值,也可以使用SETTINGS.py文件。好的,我可以看出这会与我的问题的标题混淆。然而,正如我在问题正文中所写的,我正在寻找一种方法,使全局变量可以从任何地方访问,而不必传递它。应用程序设计不是重点。这是允许日志处理程序访问全局变量的特定需要。如果它不可行,那么它就不可行……这看起来不错,如果可行,但为什么这意味着我必须将会话存储在数据库中?我不能使用本地内存空间或memcached吗?很好的一点是,如果您使用的是memcached之类的东西,就不必使用数据库。它应该可以正常工作(我没有在服务器上配置memcached,所以完全忘记了非持久性存储的memcached)是的-我一直在寻找类似的东西。@EtaiRaz好的。我认为你使用了“请求上下文”这一短语让很多人感到困惑,这一短语在Django中通常有一个。这个答案应该比这个有更多的投票权:)当代码变得复杂和分支时,它真的很有帮助-然后你突然不得不在1.10之后使用完全不同的请求,Django更改中间件的写作风格,详细信息: