Django: Как я могу получить зарегистрированного пользователя за пределами запроса просмотра?

У меня есть метод класса (вне представления), которому нужна информация о зарегистрированном пользователе. Как я могу получить вошедшего в систему пользователя, не передавая запрос методу? К сожалению, я нигде не могу найти хорошее решение, и это не логично, просто не существует такого способа сделать это, потому что Django должен где-то хранить вошедшего в систему пользователя. В противном случае (я полагаю) было бы невозможно использовать декоратор @login_required из django.contrib.auth.decorators. Верно?

Так если нельзя, то почему? Почему Django работает так, если мне нужен только зарегистрированный пользователь, а не вся информация внутри request?

Заранее спасибо.


person CodeArtist    schedule 19.04.2013    source источник


Ответы (1)


Насчет декораторов, это неправильно. На самом деле декораторы вызываются с аргументом запроса.

Я считаю, что лучшим способом является передача пользователя или объекта запроса методу класса. Но есть и другие способы доступа к запросу.

Вот код, который мы используем. Вам нужно добавить это промежуточное ПО в MIDDLEWARE. И импортировать и вызывать функцию get_request.

Обновление, июль 2017 г. Протестировано с Python 3.6.1 и Django 1.10.7 на основе исходного кода из этого ответа и Написание собственной документации по промежуточному ПО.

  • Сначала создайте новое приложение, т.е. startapp request_middleware.
  • Затем добавьте "request_middleware" к INSTALLED_APPS в settings.py.
  • После этого вставьте приведенный ниже код, т.е. request_middleware.middleware.py.
  • Наконец, добавьте "request_middleware.middleware.RequestMiddleware" к вашему MIDDLEWARE в settings.py (в моем случае я поместил его между 'debug_toolbar.middleware.DebugToolbarMiddleware' и 'django.middleware.security.SecurityMiddleware' как можно выше над списком).

# request_middleware.middleware.py

from threading import current_thread

_REQUESTS = {}


class RequestNotFound(Exception):
    def __init__(self, message):
        self.message = message


def get_request():
    thread = current_thread()
    if thread not in _REQUESTS:
        raise RequestNotFound('global request error')
    else:
        return _REQUESTS[thread]


class RequestMiddleware(object):
    def __init__(self, get_response):
        self.get_response = get_response

    def process_request(self, request):
        _REQUESTS[current_thread()] = request

    def __call__(self, request):
        self.process_request(request)
        response = self.get_response(request)

        return response

После этого просто выполните from request_middleware.middleware import get_request, чтобы использовать get_request в своем коде.

person Delgermurun    schedule 19.04.2013
comment
Я только что нашел один репозиторий github.com/tzulberti/django-request-provider, но Я не проверял это. - person Delgermurun; 19.04.2013
comment
Спасибо за ответ. На данный момент это хорошо, но я действительно хотел бы знать, почему Django работает так? Я имею в виду, почему нет другого способа получить зарегистрированного пользователя? Мне не нужна вся информация, указанная в запросе... - person CodeArtist; 19.04.2013
comment
@SalchiPapa Является ли это решение потокобезопасным? Могу ли я использовать get_request в сигнале модели post_save? - person Fabio; 09.03.2018