Guia

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

4 min de leitura

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.