Рубрики
Без рубрики

Декоратор питона и колба

Декоратор – одна из моих любимых функций Python. Поначалу, по -видимому, смущено, это просто фанк … Tagged с Python, Decorator, Flask, Tuperial.

Декоратор это одна из моих любимых функций Python. Несмотря на то, что, по -видимому, смущены сначала, это просто функция, которая принимает другую функцию в качестве параметра и возвращает другую функцию.

декоратор: фанк -> фанк

Это возможно, потому что в Python функция является первоклассным гражданином, что означает, что функция может использоваться в качестве параметра, возвращаемого значения и может быть назначена переменной.

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

По определению,

Декоратор – это функция, которая выполняет другую функцию и расширяет поведение последней функции без явного модификации ее

Конкретно приведенный ниже код:

@decorator
def f(argument):
    ...

заменит f по Декоратор (F) : звонок f (аргумент) тогда эквивалентно Декоратор (f) (аргумент) Анкет

Flask, популярная и легкая веб -структура широко использует декоратор, который приводит к элегантному и интуитивному коду. Использование Decorator можно найти по всей структуре, от определения маршрутов до добавления крючков к жизненному циклу приложения/запроса.

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

Во -первых, как реализовано @app.route?

Первый пример колбы обычно начинается с чего -то вроде:

@app.route("/")
def index():
    return "Hello world"

Имея app.route как декоратор, функция Индекс зарегистрирован для маршрута / так что когда этот маршрут запрашивается, Индекс вызывается, и его результат «Hello World» возвращается клиенту (будь то веб -браузер, curl и т. Д.).

Вы когда -нибудь задумывались, как повсеместно @app.route реализуется? Поскольку декоратор обычно используется для изменения поведения функции, его эффект обычно можно увидеть при вызываемой этой функции. Тогда как Индекс нигде не называется нигде в коде.

Непопулярным фактом о декораторе является то, что он время определения, а не время выполнения , это Индекс будет заменен на app.route ('/') (index) Когда модуль импортирован Анкет Тот факт, что этот регистр осуществляется во время определения, здесь важен, как если бы это было не так, Флеска не сможет узнать о наличии индекса.

Логика реализации @app.route на самом деле довольно просто, в основном Индекс добавляется в глобальную переменную отображения URL-функции, которая будет выполнена на поиске при появлении запроса:

class App:
    route_functions = {}
    def route(url_pattern):
        def wrap(f):
            route_functions[url_pattern] = f
            return f
        return wrap

Поэтому при замене Индекс по app.route ("/") (index) , Индекс добавляется в route_functions это содержит совместимость с функцией маршрута.

Вход в систему декоратор

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

Добавление проверки входа для каждого маршрута довольно громоздко и нарушает СУХОЙ принцип. Было бы очень удобно, если бы мы могли просто украсить такие маршруты с помощью @Login_Required, и все проверки входа будут выполнены автоматически.

@app.route("/add_tweet")
@login_required
def add_tweet():
   ...

Предположим, что проверка пользователя использует cookie, Login_Required Сначала проверяет файл cookie, если файл cookie не действителен, перенаправить пользователя на страницу входа в систему. В противном случае позвоните add_tweet :

from functools import wraps
def login_required(f):
    @wraps(f)
    def wrap(*args, **kwargs):
        # if user is not logged in, redirect to login page      
        if not request.headers["authorization"]:
            return redirect("login page")
        # get user via some ORM system
        user = User.get(request.headers["authorization"])
        # make user available down the pipeline via flask.g
        g.user = user
        # finally call f. f() now haves access to g.user
        return f(*args, **kwargs)

    return wrap

Обратите внимание, что Login_Required нужно размещать после app.route так login_required (add_tweet) будет называться, а не только add_tweet Когда маршрут соответствует. В противном случае, если Login_Required помещается до app.route , только add_tweet вызывается, когда маршрут запрашивается, и поэтому проверка требований входа не имеет никакого эффекта.

Роли на основе декоратор

Предыдущий декоратор входа может быть расширен, чтобы учитывать различные роли пользователя. Допустим, у нас есть пользователи администратора, которые могут вызывать маршруты, которые не могут другие пользователи. Было бы неплохо иметь декоратор admin_login_required , что при использовании с Login_Required Знает маршрут, доступный только для пользователей администратора.

def admin_login_required():
    def wrap(*args, **kwargs):
        # user is available from @login_required
        if not g.user.is_admin:
            return "you need to be admin", 401
return f(*args, **kwargs)

Поэтому, чтобы украсить маршрут, который требует доступа к администратору, можно просто добавить эти 2 декоратора:

@app.route("/admin/delete_user")
@login_required
@admin_login_required
def admin_delete_user():
    ...

Заказ здесь снова важен: admin_login_required Должен быть размещен после Login_Required Чтобы получить выгоду от g.user установить Login_Required Анкет

Другое использование

Использование декоратора может элегантно решить различные сухие проблемы:

  • Получите ввод из запроса запроса, JSON, форма с проверкой типов, чтобы, если ввод отсутствует или неправильно, верните 400
  • Добавьте изготовленное время, чтобы узнать, какие маршруты медленно
  • Кэширование страницы на основе параметров URL
  • И т.д

Некоторые отличные ресурсы ИМО для изучения колбы и декораторов:

https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world

http://simeonfranklin.com/blog/2012/jul/1/python-decorators-in-12-steps/

https://www.thecodeship.com/patterns/guide-to-python-function-decorators/

Оригинал: “https://dev.to/sonnk/python-decorator-and-flask-4c16”