12

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

有没有这样的东西,或者其他一些机制可以让我在请求上下文的任何地方都有一个可用的值?

蒂亚!

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

4

3 回答 3

21

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

如果您在其中创建一个中间件,例如...

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'

......或者你想做的任何事情。

于 2013-05-21T15:37:12.627 回答
5

您必须编写自己的 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')

一些有用的链接:

于 2013-05-19T11:18:41.103 回答
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

PS 我过去所做的是创建自己的表,其中包含 session_id 列和其他各种内容,然后执行 SQL 以手动根据 session_id 选择数据。比使用 SessionStore() 糖快得多

于 2013-05-19T11:20:05.487 回答