---
title: "Primeiro Projeto Flask: Guia Completo"
url: "https://python.dev.br/guias/primeiro-projeto-flask/"
markdown_url: "https://python.dev.br/guias/primeiro-projeto-flask.MD"
description: "Crie seu primeiro projeto Flask do zero. Aprenda rotas, templates, formulários, banco de dados e estrutura de projeto Python para web"
date: "2025-11-14"
author: ""
---

# 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:

```bash
mkdir blog-flask
cd blog-flask
python3 -m venv venv
source venv/bin/activate  # Linux/macOS
# venv\Scripts\activate   # Windows
```

Instale o Flask:

```bash
pip install flask
```

## Sua primeira aplicação Flask

Crie um arquivo chamado `app.py`:

```python
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:

```bash
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:

```python
@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`:

```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`:

```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:

```python
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`:

```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`:

```python
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:

```bash
pip install flask-sqlalchemy
```

Refatore o `app.py` para usar banco de dados:

```python
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:

```html
<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:

```python
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:

```html
{% 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:

```bash
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.

Se você gosta da filosofia minimalista do Flask, pode se interessar por microframeworks como Gin em <a href="https://golang.com.br/blog/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', {source: 'python.dev.br', target: 'golang.com.br', content: 'primeiro-projeto-flask'})">Go</a> ou Actix Web em <a href="https://rustlang.com.br/blog/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', {source: 'python.dev.br', target: 'rustlang.com.br', content: 'primeiro-projeto-flask'})">Rust</a>.
