What-is Flask decorator

A function that takes another function as a parameter and returns another function.

A function can be used as a parameter, a return value, and can be assigned to a variable.

Definition :
A decorator is a function that takes another function and extends the behavior of the latter function without explicitly modifying it.

Mechanism :

@decorator
def f(argument):
  1. f is replaced by decorator(f)
  2. f(argument) is equivalent decorator(f)(argument)

@wraps as a decorator

Decorators work as wrappers.

Modifying the behavior of the code, before and after a target function execution.

Allow to augmenting the original functionality, without the need to modify the function itself.

Thus decorating it.

Composition of Decorators

Function decorators are simply wrappers to existing functions.

Let's consider a function that wraps the string output of another function by p tags.

def get_text(name):
   return "lorem ipsum, {0} dolor sit amet".format(name)

def p_decorate(func):
   def func_wrapper(name):
       return "<p>{0}</p>".format(func(name))
   return func_wrapper

my_get_text = p_decorate(get_text)

print(my_get_text("John"))

# <p>Outputs lorem ipsum, John dolor sit amet</p>

Decorator Composition : syntactic sugar

There is a neat shortcut, mention the name of the decorating function before the function to be decorated. The name of the decorator should be perpended with an @ symbol.

def p_decorate(func):
   def func_wrapper(name):
       return "<p>{0}</p>".format(func(name))
   return func_wrapper

@p_decorate
def get_text(name):
   return "lorem ipsum, {0} dolor sit amet".format(name)

print(get_text("John"))

# Outputs <p>lorem ipsum, John dolor sit amet</p>

common @wrap example

This example show how to implement jwt check.

from functools import wraps

def get_token_auth_header():
  if 'Authorization' not in request.headers:
    abort(401)
  auth_header = request.headers['Authorization']
  header_parts = auth_header.split(' ')
  if len(header_parts) != 2:
    abort(401)
  elif header_parts[0].lower() != 'bearer':
    abort(401)
  return header_parts[1]

def requires_auth(f):
  @wraps(f)
  def wrapper(*args, **kwargs):
    jwt = get_token_auth_header()
    return f(jwt, *args, **kwargs)

@app.route('/taget')
@requires_auth
def target():
  print(jwt)
  return 'welcome to target'

24