O que são decoradores em python?

Estou começando um projeto em django e quero exibir uma pagina apenas quando o usuario estiver logado, pesquisando na web encontrei o @login_required, vi que isso é um decorador, mas não entendi muito bem seu uso.

1 curtida

Decorator

O decorator (ou decorador) é uma ferramenta poderosa no Python, usada para modificar o comportamento de uma função.

Como funciona

O decorator é uma função que executa outra função. Então podemos gerenciar como essa função onde usamos o decorador será executada. Podemos adicionar algum fluxo antes de executar e depois de executar, exibir alguma exception dependendo da situação, ou qualquer outra coisa.

Veja um simples exemplo de decorator:

def meu_decorator(func):
    def wrapper():
        print("Executado antes de chamar a função.")
        func()
        print("Executado depois de chamar a função.")
    return wrapper

@meu_decorator
def nossa_comunidade():
    print("Talk Code!")

nossa_comunidade()

Output

Executado antes de chamar a função.
Talk Code!
Executado depois de chamar a função.

Django e o login_required

O Django faz um ótimo trabalho com o login_required, direcionando por padrão o usuário para a página de login caso ele não esteja conectado.

Além disso ele adicionar um parametro ?next onde após fazer o login, ele retorna para a página que você tentou acessar e que possui o decorator do @login_required.

Lembrando que a página de login que ele vai redirecionar, você define no settings do django em:

settings.py

# ...
LOGIN_URL = '/accounts/login/'

Código fonte @login_required

Como você pode ver na source do Django, o login required é bem simples, e ele usa o request.user.is_authenticated para fazer essa validação.

def login_required(
    function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None
):
    """
    Decorator for views that checks that the user is logged in, redirecting
    to the log-in page if necessary.
    """
    actual_decorator = user_passes_test(
        lambda u: u.is_authenticated,
        login_url=login_url,
        redirect_field_name=redirect_field_name,
    )
    if function:
        return actual_decorator(function)
    return actual_decorator

Django staff_member_required

Assim como o @login_required, existem outros decorators no Django que facilitam a alteração de comportamento das suas Views. Por exemplo, o staff_member_required exige que o usuário logado seja tenha o atributo is_staff como True.

from django.contrib.admin.views.decorators import staff_member_required

@staff_member_required
def my_view(request): ...

Fontes