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

时间:2013-05-19 11:05:04

标签: python django

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

是否有这样的东西或其他一些机制可以让我在请求上下文的任何地方获得一个值?

TIA!

更新:我的研究只提出了一个可行的解决方案 - 线程本地人(有些人认为它不可行,但有一个非常积极的讨论,有利有弊,似乎大多数人认为你应该能够如果你负责任地在Django中使用它。)

3 个答案:

答案 0 :(得分:15)

我仍然不完全清楚你想要达到的目标,但听起来你可能会想要以下内容。

如果你创建了一个中间件,比如......

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

...然后将其添加到您的settings.py MIDDLEWARE_CLASSES作为列表中的第一项......

MIDDLEWARE_CLASSES = (
    'myproject.myapp.middleware.globalrequestmiddleware.GlobalRequestMiddleware',
    # ...
)

...然后你可以在请求/响应过程中的任何地方使用它......就像这样......

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'

......或者你想做什么。

答案 1 :(得分:4)

你必须编写自己的ContextProcessor,就像解释here一样。


编辑:

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

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')

但请注意,如果您没有将Context Processor放在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')

一些有用的链接:

答案 2 :(得分:1)

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

使用:

from django.contrib.sessions.backends.db import SessionStore

...
s = SessionStore()
s.session_key # unique_id
s['myvar'] = "something"
s.save()

这当然使用数据库和会话表,因此可能有点过多的开销。变量是特定于会话的,还是仅仅是全局成本?

文档:https://docs.djangoproject.com/en/dev/topics/http/sessions/#using-sessions-out-of-views

P.S。我过去做的是使用列session_id和其他各种东西创建我自己的表,然后完成SQL以手动选择基于session_id的数据。比使用SessionStore()糖

快得多