Django - получение доступа к request из любого места

Иногда в django при разработке проекта требуется получить доступ к текущему объекту request, но это не удаётся сделать ввиду каких-то архитектурных особенностей. Бывает что просто неудобно прокидывать этот request везде, где только можно. Было бы гораздо удобнее где-то получить его через некий модуль - синглтон. Но джанга - в отличии от PHP представляет собой постоянно работающий процесс, и каждый request у него привязан к соответствующему потоку. То есть нам нужен реквест не абы какой, а именно текущего потока. Так вот, чтобы осуществить такой функционал можно создать несложный middleware + метод получения запроса, привязанного к потоку. 

Далее прилагаю код этого middleware, который, например, можно добавть в файл приложения main/global_request_middleware.py.

Подключаем его в settings и вызываем метод get_request() там, где нам нужен запрос. Вот собственно и всё.

import threading
from django.http.request import HttpRequest
from typing import Union

GLOBAL_REQUEST_STORAGE = threading.local()


class GlobalRequestMiddleware(object):

    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        GLOBAL_REQUEST_STORAGE.request = request
        try:
            return self.get_response(request)
        finally:
            del GLOBAL_REQUEST_STORAGE.request


def get_request() -> Union[HttpRequest, None]:
    try:
        return GLOBAL_REQUEST_STORAGE.request
    except AttributeError:
        return None