// aula 1 · Python · Web com Flask
Como a internet funciona — o básico que você precisa saber
Quando você digita um endereço no navegador e aperta Enter, o navegador envia uma requisição para um computador em algum lugar do mundo — chamado de servidor. Esse servidor recebe o pedido, processa, e devolve uma resposta — geralmente uma página HTML que o navegador exibe pra você.
Isso é a web inteira. Todo site, toda API, todo sistema online funciona assim: cliente pede, servidor responde. O Flask é a ferramenta que te permite criar esse servidor usando Python.
O navegador é o cliente que faz o pedido. O Flask é a cozinha que recebe o pedido, prepara a resposta certa e manda de volta. Você, programando em Python, decide o que acontece em cada pedido.
HTTP (HyperText Transfer Protocol) é o idioma que navegadores e servidores usam para se comunicar. Toda requisição HTTP diz duas coisas principais: qual URL está sendo acessada e qual método está sendo usado.
Os métodos mais importantes são GET (quero buscar alguma coisa) e POST (quero enviar dados). Quando você abre uma página, é um GET. Quando você faz login ou envia um formulário, é um POST.
O que é Flask e por que ele existe
Flask é uma biblioteca Python que transforma seu código em um servidor web real. Sem ele, você teria que lidar manualmente com sockets de rede, parsear requisições HTTP, formatar respostas — coisas extremamente complexas. O Flask cuida de tudo isso, e deixa você focar só na lógica do seu sistema.
Ele é chamado de micro-framework não porque é fraco, mas porque começa pequeno e sem opinião — ele não te obriga a usar banco de dados X, template Y ou estrutura Z. Você escolhe o que precisa e adiciona aos poucos.
Flask foi criado por Armin Ronacher em 2010. Começou como uma piada de 1º de abril — um "framework em um arquivo só". As pessoas gostaram tanto que ele virou um projeto sério. Hoje é um dos frameworks Python mais populares do mundo, mantido por uma comunidade ativa.
Uma aplicação Flask básica cabe em 10 linhas de Python. Perfeito para aprender como a web funciona sem ter que entender um sistema gigante antes de escrever a primeira linha.
O que não vem por padrão, você adiciona com extensões: Flask-SQLAlchemy para banco de dados, Flask-Login para autenticação, Flask-Mail para e-mails. Cada uma quando você precisar.
Netflix, LinkedIn e Pinterest já usaram Flask em partes dos seus sistemas. Ele é simples de aprender, mas é robusto o suficiente para produção.
Flask é uma das escolhas mais populares para construir APIs REST em Python. Rápido de escrever, fácil de testar, e se encaixa perfeitamente com front-ends em React ou Vue.
| Flask | Django |
|---|---|
| Micro-framework — você monta o que precisa | Framework completo — vem com tudo incluso |
| Curva de aprendizado baixa — ideal para começar | Curva de aprendizado maior — mais conceitos de uma vez |
| Você escolhe banco, ORM, autenticação | Já vem com ORM, admin, autenticação prontos |
| Ideal para APIs, projetos pequenos e médios | Ideal para sistemas grandes com muitas funcionalidades |
| Estrutura livre — você organiza como quiser | Estrutura rígida e definida pelo framework |
Como o Flask funciona por dentro
Toda vez que alguém acessa uma URL da sua aplicação Flask, um ciclo acontece: o Flask recebe a requisição HTTP, identifica qual função Python deve tratar aquela URL, executa essa função, e devolve a resposta para o navegador. Esse ciclo inteiro acontece em milissegundos.
localhost:5000/produtos e aperta Enter. O navegador monta uma requisição HTTP GET e envia para o servidor Flask.
/produtos) e para o método (GET) e procura uma rota registrada que combine.
@app.route("/produtos"). Pode buscar dados no banco, processar lógica — o que você programar.
1. Werkzeug — é a biblioteca que fica embaixo do Flask e cuida de tudo relacionado ao HTTP: receber requisições, parsear formulários, lidar com cookies e muito mais. Você raramente vai interagir com ela diretamente, mas ela está sempre trabalhando.
2. Jinja2 — é o motor de templates. Ele permite que você escreva HTML com variáveis, condicionais e laços dentro, misturando Python com HTML de forma limpa e segura. Quando você chama render_template(), é o Jinja2 que entra em ação.
3. O roteador — é o coração do Flask. Quando você escreve @app.route("/sobre"), você está dizendo ao roteador: "registre que a URL /sobre deve chamar essa função". O roteador guarda essa tabela e consulta a cada requisição.
Quando você roda flask run ou app.run(debug=True), o Flask inicia um servidor embutido que é ótimo para desenvolver e testar. Mas ele não é feito para produção. Em produção, o Flask fica por trás de servidores como Gunicorn ou uWSGI, que são muito mais robustos e seguros.
Instalação e primeira rota
# 1. Crie uma pasta para o projeto mkdir meu_projeto && cd meu_projeto # 2. Crie e ative o ambiente virtual python -m venv venv source venv/bin/activate # Linux / Mac venv\Scripts\activate # Windows # 3. Instale o Flask pip install flask
O venv cria um Python isolado para cada projeto. Assim as dependências de um projeto não conflitam com as de outro. É uma boa prática que todo desenvolvedor Python segue.
O menor app Flask possível
from flask import Flask # Cria a aplicação. __name__ diz ao Flask onde estão os arquivos do projeto. app = Flask(__name__) # @app.route é um decorador — ele registra a URL "/" nessa função. @app.route("/") def index(): return "Olá, mundo! 🌍" # isso vira a resposta HTTP if __name__ == "__main__": app.run(debug=True) # debug=True reinicia ao salvar e mostra erros detalhados
python app.py
# * Running on http://127.0.0.1:5000
# Abra esse endereço no navegador!
Flask(__name__) — cria o objeto da aplicação. O __name__ é uma variável especial do Python que contém o nome do arquivo atual. O Flask usa isso para saber onde procurar templates e arquivos estáticos.
@app.route("/") — este é um decorador. Ele "envolve" a função de baixo e a registra no roteador do Flask, ligando a URL / a essa função. Quando alguém acessar /, o Flask vai chamar index().
return "Olá, mundo!" — tudo que a função retornar vira o corpo da resposta HTTP. Pode ser texto simples, HTML completo, ou JSON.
Rotas e métodos HTTP
Uma rota é a combinação de uma URL com uma função Python. É o Flask dizendo: "se alguém acessar essa URL, execute essa função e devolva o que ela retornar". Você pode ter quantas rotas quiser, cada uma tratando um endereço diferente da sua aplicação.
from flask import Flask app = Flask(__name__) @app.route("/") def index(): return "Página inicial" @app.route("/sobre") def sobre(): return "Sobre mim" # <nome> captura qualquer texto na URL e passa para a função @app.route("/usuario/<nome>") def perfil(nome): return f"Perfil de {nome}" # /usuario/lucilia → "Perfil de lucilia" # <int:id> garante que o parâmetro seja um número inteiro @app.route("/produto/<int:id>") def produto(id): return f"Produto número {id}"
Métodos HTTP — GET e POST
from flask import Flask, request app = Flask(__name__) # methods define quais métodos HTTP essa rota aceita @app.route("/contato", methods=["GET", "POST"]) def contato(): if request.method == "POST": # request.form acessa os dados enviados pelo formulário nome = request.form.get("nome") return f"Olá, {nome}! Mensagem recebida." # Se for GET, exibe o formulário return "<form method='POST'><input name='nome'><button>Enviar</button></form>"
Templates com Jinja2
Retornar HTML dentro de strings Python funciona para exemplos simples, mas vira um pesadelo em páginas reais. Templates resolvem isso: você escreve o HTML em arquivos separados, e o Jinja2 permite inserir variáveis Python dentro desse HTML de forma limpa.
É a separação entre lógica (Python) e apresentação (HTML). O Python decide os dados, o template decide como exibi-los.
meu_projeto/ ├── app.py ├── templates/ # Flask procura templates aqui automaticamente │ ├── base.html # layout base (herança de template) │ ├── index.html │ └── perfil.html └── static/ # CSS, JS e imagens ficam aqui └── style.css
Template base — herança de layout
<!DOCTYPE html> <html> <head> <title>{% block title %}Meu Site{% endblock %}</title> <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}"> </head> <body> <nav> <a href="{{ url_for('index') }}">Início</a> </nav> <main> {% block conteudo %}{% endblock %} </main> </body> </html>
Template filho — herdando o base
{% extends "base.html" %} {# herda tudo do base.html #}
{% block title %}Início{% endblock %}
{% block conteudo %}
<h1>Olá, {{ nome }}!</h1>
{% if tarefas %}
<ul>
{% for t in tarefas %}
<li>{{ t.titulo }}</li>
{% endfor %}
</ul>
{% else %}
<p>Nenhuma tarefa ainda.</p>
{% endif %}
{% endblock %}
from flask import Flask, render_template app = Flask(__name__) @app.route("/") def index(): tarefas = [ {"titulo": "Estudar Flask"}, {"titulo": "Fazer o projeto"}, ] # Tudo que você passar como argumento vira variável no template return render_template("index.html", nome="Lucilia", tarefas=tarefas)
| Sintaxe Jinja2 | O que faz |
|---|---|
{{ variavel }} | Exibe o valor de uma variável Python |
{% if ... %} {% endif %} | Condicional — bloco aparece só se a condição for verdadeira |
{% for x in lista %} {% endfor %} | Laço — repete o bloco para cada item da lista |
{% extends "base.html" %} | Herda o layout de outro template |
{% block nome %} {% endblock %} | Define um espaço que o template filho pode preencher |
{{ url_for('nome_da_funcao') }} | Gera a URL de uma rota pelo nome da função |
{# comentário #} | Comentário — não aparece no HTML final |
Recebendo dados de formulários
<form action="/adicionar" method="POST"> <input type="text" name="titulo" placeholder="Nova tarefa" required> <button type="submit">Adicionar</button> </form>
from flask import Flask, request, redirect, url_for app = Flask(__name__) tarefas = [] @app.route("/adicionar", methods=["POST"]) def adicionar(): # request.form é um dicionário com os campos do formulário titulo = request.form.get("titulo") # "titulo" = atributo name do input if titulo: tarefas.append({"titulo": titulo}) # Após POST, sempre redirecione — padrão Post/Redirect/Get return redirect(url_for("index"))
Se você retornar HTML direto após um POST e o usuário atualizar a página (F5), o navegador pergunta se quer "reenviar o formulário" — e o dado pode ser duplicado. Redirecionando para um GET com redirect(url_for(...)), o problema some. Esse padrão tem nome: Post/Redirect/Get (PRG).
Criando uma API JSON
Além de servir páginas HTML, o Flask é excelente para criar APIs. Em vez de retornar HTML, suas rotas retornam JSON — o formato de dados que front-ends React, Vue, apps mobile e qualquer cliente moderno sabem consumir. O Flask tem a função jsonify() que converte dicionários Python em JSON automaticamente.
from flask import Flask, jsonify, request app = Flask(__name__) usuarios = [ {"id": 1, "nome": "Lucilia", "email": "lucilia@email.com"}, {"id": 2, "nome": "Ana", "email": "ana@email.com"}, ] # GET /api/usuarios — retorna todos os usuários em JSON @app.route("/api/usuarios") def listar_usuarios(): return jsonify(usuarios) # converte a lista Python em JSON # GET /api/usuarios/1 — retorna um usuário específico @app.route("/api/usuarios/<int:uid>") def get_usuario(uid): u = next((u for u in usuarios if u["id"] == uid), None) if not u: return jsonify({"erro": "não encontrado"}), 404 # segundo valor = status HTTP return jsonify(u) # POST /api/usuarios — cria um novo usuário @app.route("/api/usuarios", methods=["POST"]) def criar_usuario(): dados = request.get_json() # lê o corpo JSON da requisição novo = { "id": len(usuarios) + 1, "nome": dados["nome"], "email": dados["email"] } usuarios.append(novo) return jsonify(novo), 201 # 201 Created — recurso criado com sucesso
| Código HTTP | Significado | Quando usar |
|---|---|---|
200 OK | Tudo certo | Resposta padrão de sucesso (Flask usa por padrão) |
201 Created | Criado com sucesso | Após um POST que cria um novo recurso |
400 Bad Request | Requisição inválida | Dados enviados pelo cliente estão errados |
404 Not Found | Não encontrado | Recurso não existe no servidor |
500 Internal Server Error | Erro no servidor | Algo deu errado no código do servidor |
Mini projeto — Lista de Tarefas
Uma lista de tarefas funcional no navegador — você adiciona e remove tarefas, com tudo processado pelo Flask. Os dados ficam em memória para focar no Flask puro, sem banco de dados ainda.
tarefas_app/
├── app.py
└── templates/
└── index.html
from flask import Flask, render_template, request, redirect, url_for app = Flask(__name__) tarefas = [] proximo_id = 1 @app.route("/") def index(): return render_template("index.html", tarefas=tarefas) @app.route("/adicionar", methods=["POST"]) def adicionar(): global proximo_id titulo = request.form.get("titulo", "").strip() if titulo: tarefas.append({"id": proximo_id, "titulo": titulo}) proximo_id += 1 return redirect(url_for("index")) @app.route("/remover/<int:tid>") def remover(tid): global tarefas tarefas = [t for t in tarefas if t["id"] != tid] return redirect(url_for("index")) if __name__ == "__main__": app.run(debug=True)
<!DOCTYPE html> <html lang="pt-BR"> <head><title>Tarefas</title></head> <body> <h1>📝 Minhas Tarefas</h1> <form action="/adicionar" method="POST"> <input type="text" name="titulo" placeholder="Nova tarefa..." required> <button>Adicionar</button> </form> {% if tarefas %} <ul> {% for t in tarefas %} <li> {{ t.titulo }} <a href="/remover/{{ t.id }}">❌</a> </li> {% endfor %} </ul> {% else %} <p>Nenhuma tarefa ainda!</p> {% endif %} </body> </html>
As tarefas somem ao reiniciar o servidor pois ficam em memória. O próximo passo é conectar ao PostgreSQL com psycopg2 ou SQLAlchemy para persistir os dados. Ou dar um salto maior e conhecer o Django — que já vem com banco de dados integrado desde o início.