Rotas e formulários: páginas que recebem dados
Capture dados da URL e de formulários HTML para criar páginas interativas.
Rotas dinâmicas no Flask
Uma das funcionalidades mais úteis do Flask é a possibilidade de criar rotas dinâmicas. Em vez de definir uma URL fixa para cada página, você captura partes da URL como variáveis e usa esses valores dentro da função.
A sintaxe é simples: basta colocar o nome da variável entre < e > na rota.
from flask import Flask
app = Flask(__name__)
@app.route("/usuario/<nome>")
def perfil(nome):
return f"Bem-vindo, {nome}!"
Ao acessar /usuario/maria, a variável nome recebe o valor "maria" e a página exibe a saudação correspondente.
Conversores de tipo
Por padrão, toda variável capturada na URL chega como string. Mas o Flask oferece conversores que validam e convertem o tipo automaticamente. Se o valor não bater com o tipo esperado, o Flask retorna um erro 404.
@app.route("/produto/<int:id>")
def produto(id):
return f"Produto de ID: {id}"
@app.route("/arquivo/<path:caminho>")
def arquivo(caminho):
return f"Caminho solicitado: {caminho}"
Os conversores disponíveis são:
string— aceita qualquer texto sem barra (padrão)int— aceita números inteirosfloat— aceita números decimaispath— como string, mas aceita barrasuuid— aceita strings no formato UUID
Você pode combinar mais de uma variável na mesma rota sem problema:
@app.route("/loja/<string:categoria>/<int:pagina>")
def listar(categoria, pagina):
return f"Categoria: {categoria} | Pagina: {pagina}"
Gerando URLs com url_for()
Escrever URLs manualmente no código é arriscado: se você mudar a rota, precisa atualizar todos os lugares onde ela aparece. O url_for() resolve isso gerando a URL a partir do nome da função.
from flask import Flask, url_for
app = Flask(__name__)
@app.route("/")
def inicio():
link = url_for("perfil", nome="joao")
return f'<a href="{link}">Ver perfil do Joao</a>'
@app.route("/usuario/<nome>")
def perfil(nome):
return f"Perfil de {nome}"
As vantagens são claras: se a rota /usuario/<nome> mudar para /u/<nome>, o url_for() continua funcionando sem precisar alterar o restante do código. Além disso, ele cuida automaticamente da codificação de caracteres especiais na URL.
O objeto request
Para acessar dados enviados pelo navegador, o Flask disponibiliza o objeto request. Ele contém informações sobre a requisição atual: parâmetros da URL, dados de formulários, método HTTP e muito mais.
from flask import Flask, request
app = Flask(__name__)
@app.route("/busca")
def busca():
termo = request.args.get("q", "")
pagina = request.args.get("pagina", 1, type=int)
return f"Buscando por: {termo} | Pagina: {pagina}"
Ao acessar /busca?q=flask&pagina=2, o request.args captura os parâmetros da query string. O método .get() aceita um valor padrão e até um tipo para conversão automática.
Os atributos mais usados do request são:
request.args— parâmetros da query string (GET)request.form— dados enviados por formulário (POST)request.method— método HTTP da requisição (GET,POST, etc.)request.files— arquivos enviados via upload
Formulários HTML com POST
Para enviar dados ao servidor, o caminho mais comum é criar um formulário HTML que usa o método POST. No Flask, a mesma rota pode aceitar GET e POST usando o parâmetro methods.
from flask import Flask, request, render_template_string
app = Flask(__name__)
FORMULARIO = """
<form method="POST" action="/login">
<input type="text" name="email" placeholder="E-mail">
<input type="password" name="senha" placeholder="Senha">
<button type="submit">Entrar</button>
</form>
"""
@app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "POST":
email = request.form.get("email")
senha = request.form.get("senha")
return f"Login recebido: {email}"
return FORMULARIO
Quando o usuário acessa /login pelo navegador, o método é GET e o formulário é exibido. Quando ele preenche e clica em "Entrar", o navegador envia os dados via POST e a mesma função trata o envio.
Validação básica no servidor
Nunca confie apenas na validação do lado do cliente. O servidor precisa verificar se os dados recebidos estão corretos antes de processá-los.
@app.route("/cadastro", methods=["GET", "POST"])
def cadastro():
erros = []
if request.method == "POST":
nome = request.form.get("nome", "").strip()
email = request.form.get("email", "").strip()
if not nome:
erros.append("O nome e obrigatorio.")
if not email or "@" not in email:
erros.append("Informe um e-mail valido.")
if not erros:
# salvar no banco de dados
return "Cadastro realizado com sucesso!"
return render_template_string("""
{% for erro in erros %}
<p style="color:red">{{ erro }}</p>
{% endfor %}
<form method="POST">
<input name="nome" placeholder="Nome">
<input name="email" placeholder="E-mail">
<button>Cadastrar</button>
</form>
""", erros=erros)
A validação acontece inteiramente no servidor. Os erros são coletados em uma lista e exibidos acima do formulário para que o usuário corrija os campos.
Flash messages para feedback
O Flask possui um sistema embutido de mensagens temporárias chamado flash messages. Elas são perfeitas para exibir avisos como "Cadastro realizado!" ou "Erro ao salvar" após um redirecionamento.
from flask import Flask, flash, get_flashed_messages, redirect, url_for, request
app = Flask(__name__)
app.secret_key = "chave-secreta"
@app.route("/salvar", methods=["POST"])
def salvar():
nome = request.form.get("nome", "").strip()
if not nome:
flash("O campo nome nao pode ficar vazio.", "erro")
else:
flash("Dados salvos com sucesso!", "sucesso")
return redirect(url_for("formulario"))
@app.route("/formulario")
def formulario():
mensagens = get_flashed_messages(with_categories=True)
html = ""
for categoria, msg in mensagens:
cor = "green" if categoria == "sucesso" else "red"
html += f'<p style="color:{cor}">{msg}</p>'
html += """
<form method="POST" action="/salvar">
<input name="nome" placeholder="Seu nome">
<button>Salvar</button>
</form>
"""
return html
As flash messages ficam armazenadas na sessão do usuário e são consumidas automaticamente na próxima requisição. Isso significa que, ao recarregar a página, a mensagem desaparece.
Redirect após POST (padrão PRG)
O padrão Post/Redirect/Get (PRG) resolve um problema clássico: quando o usuário atualiza a página após um envio de formulário, o navegador reenvia os dados. Isso pode causar duplicações indesejadas.
A solução é simples: após processar o POST, redirecione o usuário para uma rota GET.
from flask import Flask, request, redirect, url_for, flash
app = Flask(__name__)
app.secret_key = "chave-secreta"
@app.route("/contato", methods=["GET", "POST"])
def contato():
if request.method == "POST":
# processa os dados
flash("Mensagem enviada!")
return redirect(url_for("contato"))
# exibe o formulario no GET
return "<form method='POST'><button>Enviar</button></form>"
Após o redirect, o navegador faz uma nova requisição GET. Se o usuário apertar F5, apenas o GET é repetido — sem reenvio do formulário.
Exemplo prático: formulário de contato
Vamos juntar tudo em um exemplo completo: um formulário de contato com validação no servidor, flash messages e o padrão PRG.
from flask import (
Flask, request, redirect, url_for,
flash, get_flashed_messages, render_template_string,
)
app = Flask(__name__)
app.secret_key = "minha-chave-secreta"
TEMPLATE_CONTATO = """
<!DOCTYPE html>
<html>
<head><title>Contato</title></head>
<body>
<h1>Fale conosco</h1>
{% for cat, msg in get_flashed_messages(with_categories=true) %}
<p style="color:{{ 'green' if cat == 'sucesso' else 'red' }}">
{{ msg }}
</p>
{% endfor %}
<form method="POST" action="{{ url_for('contato') }}">
<label>Nome:</label><br>
<input type="text" name="nome"><br><br>
<label>E-mail:</label><br>
<input type="email" name="email"><br><br>
<label>Mensagem:</label><br>
<textarea name="mensagem" rows="5" cols="40"></textarea><br><br>
<button type="submit">Enviar</button>
</form>
</body>
</html>
"""
@app.route("/contato", methods=["GET", "POST"])
def contato():
if request.method == "POST":
nome = request.form.get("nome", "").strip()
email = request.form.get("email", "").strip()
mensagem = request.form.get("mensagem", "").strip()
if not nome:
flash("Preencha o campo nome.", "erro")
if not email or "@" not in email:
flash("Informe um e-mail valido.", "erro")
if not mensagem:
flash("A mensagem nao pode ficar vazia.", "erro")
erros = get_flashed_messages()
if not erros:
# aqui voce enviaria o e-mail ou salvaria no banco
flash("Mensagem enviada com sucesso!", "sucesso")
return redirect(url_for("contato"))
return render_template_string(TEMPLATE_CONTATO)
if __name__ == "__main__":
app.run(debug=True)
O fluxo completo funciona assim: o usuário acessa /contato via GET e vê o formulário. Ao submeter, o servidor valida os campos. Se houver erros, o formulário é reexibido com as mensagens em vermelho. Se tudo estiver correto, uma flash message de sucesso é criada e o usuário é redirecionado para a mesma rota via GET — aplicando o padrão PRG.
Com essas ferramentas — rotas dinâmicas, url_for(), o objeto request, validação, flash messages e o padrão PRG — você já consegue construir páginas interativas completas no Flask.