|Ned Batchelder : Blog | Code | Text | Site|
Global Django requests
» Home : Blog : August 2010
As my Django sites get larger and larger, there inevitably comes a point where I want access to the current request from deep inside some function that doesn't have the request object. The latest reason was that I wanted a model class helper to have access to the session so it could access some debug flags.
The first option for making this work was to pass the request object through two or three layers of code that otherwise didn't need a request. This meant changing the signature and callers of the two or three functions, which felt messy. The prospect of it made me unhappy.
The second option was to create a way for any code invoked as part of a request to get access to the request, even if it weren't passed to it explicitly. I think of this as a global request object.
Of course, there isn't really a single global request object, since there can be many threads, each of which is handling a separate request. We need a way to associate the request with a thread, and then to get the request for our thread. This middleware does the job nicely:
I didn't write this code, I got it from here and here, not sure who wrote it first. I'm also not sure why Django provides its own currentThread function when the Python standard module threading provides thread locals to acheive the same effect.
There's another way to get a global request object, but you probably won't like it:
This function looks at the stack frames of all of its callers, looking for one with a first argument named "request". If found, it returns the value. The problem with this function is that it can be fooled, and will return the "request" it finds regardless of its type.
In its defense: GlobalRequestMiddleware requires more machinery, and adds a tiny tax to every request. If your need for the global request object is rare, the frame-based get_request() may be better for you. Also, it's a (nasty) technique that can be adapted to other situations.
tagged: django» 8 reactions