К какой информации имеют доступ декораторы Python/Django?

Я делаю рефакторинг в нашем коде. Декоратор @render_to_json внутренне вызывал метод is_logged_in. Я удаляю это в пользу простого добавления другого явного декоратора @login_required.

Проблема в том, что некоторые из наших методов вызываются через AJAX и ожидают ответа json {"status": "logged_out"}, на который они затем воздействуют. Поэтому мне нужно изменить наш метод login_required, чтобы как-то проверить одну из двух вещей.

  • Был ли этот метод вызван через AJAX, возможно, обнаружение заголовка XMLHttpRequest
  • Был ли также вызван декоратор render_to_json для этого запроса. Мысль заключалась бы в том, что если бы метод login_required знал, что запрос ожидает json, то он мог бы вернуть пакет json, иначе перенаправить как обычно.

ОБНОВЛЕНИЕ Добавление третьего варианта.

  • В каждом случае метод с декоратором @render_to_json, перед ним указывается декоратор @login_required. Метод @login_required возвращает HttpResponseRedirect, если пользователь вышел из системы. Как в методе @render_to_json проверить возвращаемый тип метода login_required и ответить соответствующим образом?

Мысли? Проблемы?

Я должен добавить, что я также довольно новичок в Python, поэтому я могу упустить что-то основное. Если да, то помогите мне научиться?

ОБНОВЛЕНИЕ

Я собираюсь добавить сюда двух декораторов для справки.

def render_to_json(fn):

    @wraps(fn)
    def inner(request, *args, **kwargs):
        result = fn(request, *args, **kwargs)
        return HttpResponse(json.dumps(result), mimetype='application/json')

    return inner

def login_required(func):
    @wraps(func)
    def _decorator(request, *args, **kwargs):
        if not is_logged_in(request):
            from apps.core.extendedLogging import ExtendedLogging
            ExtendedLogging.log("In login req'd: it appears that the user is not logged in", request)
            request.session['login_referrer_uri'] = request.build_absolute_uri()
            return HttpResponseRedirect(settings.LOGIN_URL)
        return func(request, *args, **kwargs)
    return _decorator

person commadelimited    schedule 31.01.2013    source источник
comment
Декоратор имеет доступ ко всем аргументам, с которыми вызывается функция, которую он украшает, поэтому я не уверен, что понимаю первый пункт.   -  person David Robinson    schedule 31.01.2013
comment
Дэйвид. Помните, что я новичок в Python в целом. Я подозревал, что так и будет, но не был уверен. Согласно этому сообщению, я бы использовал request.META, чтобы получить доступ ко всем заголовкам запросов? stackoverflow.com/questions/3889769/   -  person commadelimited    schedule 31.01.2013
comment
Я бы специально искал этот заголовок запроса X-Requested-With XMLHttpRequest   -  person commadelimited    schedule 31.01.2013


Ответы (1)


Декораторы могут получить доступ ко всем данным, которые получает «Decoratee»:

def method_decorator(operation):
    """
    On this case operation = view_method
    """
    def wrapper(*args, **kwargs):
        """
        Receives all arguments the requested operation would receive
        """
            request = args[0]
            param = args[1]
            more_param = args[2]

            return operation(request, param, more_param)
    return wrapper

@method_decorator
def view_method(request, param, more_param):
    #something

поэтому, когда вы вызываете «view_method», сначала вы бросаете «method_decorator», который затем вызывает «view_method».

Теперь в декораторе вы можете проверить все, что вам нужно, и передать эту новую информацию, например:

def wrapper(*args, **kwargs):
        ...
        if some_condition:
            request.new_content = new_content
        return operation(request, param, more_param)
return wrapper

Это позволит вам получить new_content по запрошенному методу view_method:

@method_decorator
def view_method(request, param, more_param):
    new_content = request.new_content

И, надеюсь, метод view_method теперь знает, что делать.

Вы также можете передавать данные от декоратора к декоратору с помощью того же метода.

person Damium    schedule 31.01.2013
comment
Спасибо. Очень подробный ответ... ценю ваше время. - person commadelimited; 31.01.2013