Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to access the context from everywhere in Django?

Tags:

python

django

I'm looking for a way to have a global variable that is accessible by any module within my django request without having to pass it around as parameter. Traditionally in other MVCs, I would store it in the request context or session and access the context with something like a "get_current_context" method (which I couldn't find in Django).

Is there something like this, or some other mechanism that will allow me to have a value available from anywhere in the request context?

TIA!

UPDATE: My research has only come up with one viable solution - thread locals (some would argue it's not viable, but there's a pretty active discussion about it, with pros and cons and seems like most people think you should be able to use it in Django, if you do it responsibly).

like image 861
one eyed dev Avatar asked May 19 '13 11:05

one eyed dev


2 Answers

It's still not completely clear to me what you're trying to achieve, but it sounds like you might want something like the following.

If you create a piece of middleware in, say...

myproject/myapp/middleware/globalrequestmiddleware.py

...which looks like this...

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

...then add it into your settings.py MIDDLEWARE_CLASSES as the first item in the list...

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

...then you can use it anywhere in the request/response process like this...

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'

...or whatever it is you want to do.

like image 67
Aya Avatar answered Oct 12 '22 13:10

Aya


You have to write your own ContextProcessor, like explained here.


EDIT:

After you've created a Context Processor, e.g.,

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

you can get the variables you need by initializing a RequestContext, like this:

from django.template import RequestContext

def myview(request):
  rc = RequestContext(request)
  rc.get('ip_address')

However, please note that if you don't put your Context Processor inside the TEMPLATE_CONTEXT_PROCESSORS tuple, you have to pass the processor to RequestContext as an argument, e.g.:

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

Some useful links:

  • Django Template API documentation
  • Settings TEMPLATE_CONTEXT_PROCESSORS
  • Django Book: Advanced Templates
like image 21
Markon Avatar answered Oct 12 '22 11:10

Markon