Can I safely use contextvar with django?

Hello,
I need to store the request object globally, so non-view function can reference it without explicity passing it as a parameter.

I tried to write middleware that store the request object in contextvar, However, I would like to ask about the safety of this approach?

2 Likes

In general, an extremely bad idea.

Pass the request as a parameter.

1 Like

@KenWhitesell Can you say more about why a global request object is considered a bad idea?

The warning is about the attempt to create any “global” object. The concept of “global” isn’t “solid” across various Django deployment environments. They’re not necessarily thread-safe.

Briefly, because of the variety of contexts with which Django projects are run, there are multiple potential conflicts between concurrent requests in other threads - or even within the same thread in an async context.

Are you definitely always going to encounter problems? No. There are ways of doing it, especially in well-defined and constrained environments. But personally, I would never consider the risk worthwhile. Whatever nominal benefit may exist just isn’t work the risk from my perspective.

As far as I’m concerned, it’s a whole lot better to forgo trying to cover all the edge cases of doing this and use a different mechanism - perhaps the user session if suitable or some other general storage - perhaps the cache, or directly use redis or your database.

Thanks @KenWhitesell.

Would you say these concerns also apply when using a global for the sole purpose of creating a request based cache with a ContextVar for the current request?

From where I sit, the concerns always apply. It’s an architectural decision I consider absolute.

Across 11 years now working with Django, and more than a dozen years beyond that working with a half dozen other web frameworks, I’ve never found a situation where I consider any global to be a necessary (or desirable) option. Yes there are situations where it can be done safely, but I’d rather spend my effort elsewhere.