Имеет ли значение порядок декораторов в представлении Flask?

Я использую декоратор login_required и еще один декоратор, который разбивает выходные данные на страницы. Важно, какой из них будет первым?


person shalbafzadeh    schedule 28.01.2015    source источник


Ответы (4)


Хотя в этом случае, вероятно, не будет никаких проблем, независимо от порядка, вы, вероятно, захотите, чтобы login_required выполнялся первым, чтобы вы не делали запросы и не разбивали результаты на страницы, которые будут просто отброшены.

Декораторы оборачивают исходную функцию снизу вверх, поэтому при вызове функции обертка, добавленная каждым декоратором, выполняется сверху вниз. @login_required должен быть ниже любых других декораторов, которые предполагают, что пользователь вошел в систему, чтобы его состояние оценивалось раньше этих других.

@app.route() всегда должен быть верхним, самым внешним декоратором. В противном случае маршрут будет зарегистрирован для функции, которая не представляет все декораторы.


Более широкий ответ заключается в том, что это зависит от того, что делает каждый из декораторов. Вам нужно подумать о потоке вашей программы и о том, будет ли логично, чтобы одно предшествовало другому.

person davidism    schedule 28.01.2015

согласно реализации login_required,

def login_required(func):
    @wraps(func)
    def decorated_view(*args, **kwargs):
        if current_app.login_manager._login_disabled:
            return func(*args, **kwargs)
        elif not current_user.is_authenticated():
            return current_app.login_manager.unauthorized()
        return func(*args, **kwargs)
    return decorated_view

Вы должны сделать это, как показано ниже.

@login_required
@paginate
def view_function():
    pass

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

@login_required
@is_admin
def view_function():
    pass
person user1900344    schedule 28.04.2018

В документации Flask указано, что порядок имеет значение, если функция является представлением и имеет декоратор route. Из документов:

При применении дополнительных декораторов всегда помните, что декоратор route() является самым внешним.

person leafmeal    schedule 19.09.2018

Согласно PEP 318 синтаксис декораторов функций следующий:

@dec2
@dec1
def func(arg1, arg2, ...):
    pass

это эквивалентно:

def func(arg1, arg2, ...):
    pass
func = dec2(dec1(func))

и dec1 вызывается перед dec2.

Вы можете определить эти функции для проверки следующим образом:

def dec1(func):
    print 'dec1'
def dec2(func):
    print 'dec2'

@dec2
@dec1
def func():
    pass
dec1
dec2

На самом деле это не вызывает никаких ошибок, но если вы сначала используете login_reqired, а пользователь не вошел в систему, приложение будет обрабатывать данные и разбивать их на страницы после того, как эта функция login_required сгенерирует прерывание.

Лучшая реализация декоратора login_required в колбе:

@paginate
@login_required
def view_function():
    pass
person rezakamalifard    schedule 28.01.2015
comment
Хотя все, что приводит к выводу в вашем ответе, технически правильно, ваш вывод абсолютно неверен. Вы хотите поместить @login_required над @paginate -- позвольте мне объяснить, почему... Несмотря на то, что декораторы технически выполняются снизу вверх, вы должны помнить, что когда декоратор выполняется, он возвращает оболочку. В оболочке должны выполняться основные функции декоратора... а оболочки декоратора выполняются сверху вниз. - person Jimmy Huch; 12.09.2018