Primeiro Projeto Flask: Guia Completo
Crie seu primeiro projeto Flask do zero. Aprenda rotas, templates, formulários, banco de dados e estrutura de projeto Python para web
Introdução
Flask é um microframework web para Python, conhecido por sua simplicidade e flexibilidade. Diferente do Django, que vem com muitas funcionalidades embutidas, o Flask oferece o mínimo necessário e permite que você escolha as bibliotecas para cada necessidade do projeto.
Empresas como Netflix, LinkedIn e Uber usam Flask em partes de suas aplicações. Neste guia, vamos criar uma aplicação web completa do zero usando Flask.
Pré-requisitos
- Python 3.10 ou superior
- Conhecimento básico de HTML
- Familiaridade com o terminal
Configurando o ambiente
Crie uma pasta para o projeto e configure o ambiente virtual:
mkdir blog-flask
cd blog-flask
python3 -m venv venv
source venv/bin/activate # Linux/macOS
# venv\Scripts\activate # Windows
Instale o Flask:
pip install flask
Sua primeira aplicação Flask
Crie um arquivo chamado app.py:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return '<h1>Bem-vindo ao meu blog!</h1>'
if __name__ == '__main__':
app.run(debug=True)
Execute a aplicação:
python app.py
Acesse http://127.0.0.1:5000/ no navegador. Você verá a mensagem de boas-vindas. O modo debug=True reinicia o servidor automaticamente quando você altera o código.
Entendendo rotas
Rotas conectam URLs a funções Python. Cada decorator @app.route() define um caminho:
@app.route('/')
def index():
return 'Pagina inicial'
@app.route('/sobre')
def sobre():
return 'Sobre o blog'
@app.route('/post/<int:post_id>')
def ver_post(post_id):
return f'Exibindo o post {post_id}'
O Flask suporta parâmetros dinâmicos nas URLs usando <variavel>. Você pode especificar o tipo com <int:variavel>, <float:variavel> ou <path:variavel>.
Usando templates com Jinja2
Retornar HTML diretamente das funções não é prático. O Flask usa o Jinja2 como motor de templates. Crie a pasta templates/ e dentro dela o arquivo base.html:
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Meu Blog{% endblock %}</title>
<style>
body { font-family: Georgia, serif; max-width: 700px; margin: 40px auto; padding: 0 20px; line-height: 1.6; }
nav a { margin-right: 15px; }
</style>
</head>
<body>
<nav>
<a href="{{ url_for('index') }}">Inicio</a>
<a href="{{ url_for('sobre') }}">Sobre</a>
</nav>
<hr>
{% block content %}{% endblock %}
</body>
</html>
Agora crie templates/index.html:
{% extends "base.html" %}
{% block title %}Inicio - Meu Blog{% endblock %}
{% block content %}
<h1>Ultimos Posts</h1>
{% for post in posts %}
<article>
<h2><a href="{{ url_for('ver_post', post_id=post.id) }}">{{ post.titulo }}</a></h2>
<p>{{ post.conteudo[:150] }}...</p>
<small>Publicado em {{ post.data }}</small>
</article>
<hr>
{% endfor %}
{% endblock %}
Atualize app.py para usar templates:
from flask import Flask, render_template
app = Flask(__name__)
# Dados temporarios (depois usaremos banco de dados)
posts = [
{'id': 1, 'titulo': 'Aprendendo Flask', 'conteudo': 'Flask e um microframework web...', 'data': '2025-11-01'},
{'id': 2, 'titulo': 'Python para Web', 'conteudo': 'Python oferece varios frameworks...', 'data': '2025-11-05'},
]
@app.route('/')
def index():
return render_template('index.html', posts=posts)
Trabalhando com formulários
Para receber dados do usuário, precisamos de formulários. Crie templates/criar_post.html:
{% extends "base.html" %}
{% block content %}
<h1>Novo Post</h1>
<form method="POST">
<div>
<label>Titulo:</label><br>
<input type="text" name="titulo" required style="width:100%; padding:8px;">
</div>
<div style="margin-top:10px;">
<label>Conteudo:</label><br>
<textarea name="conteudo" rows="10" required style="width:100%; padding:8px;"></textarea>
</div>
<button type="submit" style="margin-top:10px; padding:10px 20px;">Publicar</button>
</form>
{% endblock %}
Adicione a rota em app.py:
from flask import Flask, render_template, request, redirect, url_for
@app.route('/criar', methods=['GET', 'POST'])
def criar_post():
if request.method == 'POST':
titulo = request.form['titulo']
conteudo = request.form['conteudo']
novo_post = {
'id': len(posts) + 1,
'titulo': titulo,
'conteudo': conteudo,
'data': '2025-11-14'
}
posts.append(novo_post)
return redirect(url_for('index'))
return render_template('criar_post.html')
Adicionando banco de dados com SQLite
Para persistir dados, vamos usar o Flask-SQLAlchemy. Instale:
pip install flask-sqlalchemy
Refatore o app.py para usar banco de dados:
from flask import Flask, render_template, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///blog.db'
db = SQLAlchemy(app)
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
titulo = db.Column(db.String(200), nullable=False)
conteudo = db.Column(db.Text, nullable=False)
data = db.Column(db.DateTime, default=datetime.utcnow)
def __repr__(self):
return f'<Post {self.titulo}>'
with app.app_context():
db.create_all()
@app.route('/')
def index():
posts = Post.query.order_by(Post.data.desc()).all()
return render_template('index.html', posts=posts)
@app.route('/criar', methods=['GET', 'POST'])
def criar_post():
if request.method == 'POST':
titulo = request.form['titulo']
conteudo = request.form['conteudo']
post = Post(titulo=titulo, conteudo=conteudo)
db.session.add(post)
db.session.commit()
return redirect(url_for('index'))
return render_template('criar_post.html')
@app.route('/post/<int:post_id>')
def ver_post(post_id):
post = Post.query.get_or_404(post_id)
return render_template('post.html', post=post)
@app.route('/sobre')
def sobre():
return render_template('sobre.html')
if __name__ == '__main__':
app.run(debug=True)
Arquivos estáticos
Coloque CSS, JavaScript e imagens na pasta static/. Para referenciar no template:
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
Crie static/style.css para estilizar sua aplicação conforme necessário.
Mensagens flash
O Flask oferece mensagens flash para feedback ao usuário:
from flask import flash
app.secret_key = 'sua-chave-secreta-aqui'
@app.route('/criar', methods=['GET', 'POST'])
def criar_post():
if request.method == 'POST':
# ... criar post ...
flash('Post criado com sucesso!')
return redirect(url_for('index'))
return render_template('criar_post.html')
No template, exiba as mensagens:
{% for mensagem in get_flashed_messages() %}
<div style="background:#d4edda; padding:10px; margin:10px 0;">
{{ mensagem }}
</div>
{% endfor %}
Estrutura de projeto recomendada
Para projetos maiores, organize com o padrão Application Factory:
blog-flask/
app/
__init__.py
models.py
routes.py
templates/
static/
config.py
run.py
requirements.txt
Gere o arquivo de dependências:
pip freeze > requirements.txt
Conclusão
O Flask é uma excelente escolha para quem quer aprender desenvolvimento web com Python. Sua simplicidade permite entender como cada parte de uma aplicação web funciona, sem a abstração de frameworks maiores. A partir daqui, explore extensões como Flask-Login para autenticação, Flask-Migrate para migrações de banco e Flask-WTF para formulários seguros. A documentação oficial do Flask em flask.palletsprojects.com é uma das melhores referências disponíveis.