Programador Leigo
Flask 10 min leitura 11 MAR 2026

Conectando seu site a um banco de dados MongoDB

Conecte seu app Flask ao MongoDB e implemente operações CRUD com PyMongo.


Por que MongoDB para projetos Flask

O MongoDB é um banco de dados NoSQL orientado a documentos. Em vez de tabelas e linhas, você trabalha com coleções e documentos JSON. Isso combina muito bem com o Flask por alguns motivos:

  • Flexibilidade de esquema — você não precisa definir colunas antes de inserir dados. Isso acelera a prototipagem e permite evoluir a estrutura dos dados sem migrações.
  • Formato nativo — os documentos são armazenados em BSON (JSON binário), o que facilita a comunicação entre o banco e a API, já que o Flask trabalha naturalmente com dicionários Python.
  • Escalabilidade horizontal — o MongoDB foi projetado para distribuir dados entre múltiplos servidores, o que é útil quando sua aplicação cresce.

Se o seu projeto tem dados com estrutura variável ou você quer começar rápido sem se preocupar com esquemas rígidos, o MongoDB é uma ótima escolha.

Instalação do PyMongo e conexão

O PyMongo é o driver oficial do MongoDB para Python. Instale junto com o Flask:

pip install flask pymongo

Para conectar, basta informar a URI do MongoDB. Em desenvolvimento local, o padrão é localhost na porta 27017:

from pymongo import MongoClient

client = MongoClient("mongodb://localhost:27017/")
db = client["meu_banco"]

A variável db agora representa o banco de dados. A partir dela, você acessa qualquer coleção.

Estrutura: onde colocar a conexão no app

Em projetos pequenos, você pode criar a conexão diretamente no arquivo principal. Porém, à medida que o projeto cresce, é melhor isolar a configuração do banco em um módulo separado.

Uma abordagem comum é criar um arquivo database.py:

# database.py
import os
from pymongo import MongoClient

MONGO_URI = os.environ.get("MONGO_URI", "mongodb://localhost:27017/")
client = MongoClient(MONGO_URI)
db = client["flask_app"]

Depois, no seu arquivo principal ou nas rotas, basta importar:

# app.py
from flask import Flask
from database import db

app = Flask(__name__)
tarefas = db["tarefas"]

Dessa forma, toda a aplicação compartilha a mesma conexão, e você pode trocar a URI via variável de ambiente em produção sem alterar o código.

Create: insert_one e insert_many

Para inserir um único documento, use insert_one. Ele retorna o _id gerado automaticamente pelo MongoDB:

resultado = tarefas.insert_one({
    "titulo": "Estudar PyMongo",
    "concluida": False
})
print(resultado.inserted_id)

Para inserir vários documentos de uma vez, use insert_many:

novas_tarefas = [
    {"titulo": "Configurar MongoDB", "concluida": True},
    {"titulo": "Criar rotas CRUD", "concluida": False},
    {"titulo": "Escrever testes", "concluida": False},
]
resultado = tarefas.insert_many(novas_tarefas)
print(resultado.inserted_ids)

Read: find_one, find com filtros e projeções

Para buscar um único documento, use find_one. Ele retorna o primeiro documento que corresponde ao filtro ou None se não encontrar nada:

tarefa = tarefas.find_one({"titulo": "Estudar PyMongo"})
print(tarefa)

Para buscar vários documentos, use find. Ele retorna um cursor que você pode iterar:

pendentes = tarefas.find({"concluida": False})
for tarefa in pendentes:
    print(tarefa["titulo"])

Você também pode usar projeções para controlar quais campos retornam na consulta. Isso é útil para evitar tráfego desnecessário:

# Retorna apenas o titulo, sem o _id
resultados = tarefas.find(
    {"concluida": False},
    {"titulo": 1, "_id": 0}
)

Para buscar por _id, lembre-se de converter a string para ObjectId:

from bson.objectid import ObjectId

tarefa = tarefas.find_one({"_id": ObjectId("664f1a2b3c4d5e6f7a8b9c0d")})

Update: update_one com $set

O operador $set atualiza apenas os campos especificados, sem sobrescrever o documento inteiro:

tarefas.update_one(
    {"titulo": "Estudar PyMongo"},
    {"$set": {"concluida": True}}
)

O update_one retorna um objeto com informações sobre a operação. Você pode verificar quantos documentos foram modificados:

resultado = tarefas.update_one(
    {"titulo": "Estudar PyMongo"},
    {"$set": {"concluida": True}}
)
print(resultado.modified_count)  # 1

Delete: delete_one

Para remover um documento, use delete_one com um filtro:

resultado = tarefas.delete_one({"titulo": "Estudar PyMongo"})
print(resultado.deleted_count)  # 1

Cuidado: se o filtro corresponder a mais de um documento, apenas o primeiro será removido. Para remover vários, use delete_many.

Índices e unique constraints

Índices melhoram a velocidade das consultas. Sem eles, o MongoDB precisa percorrer todos os documentos da coleção para encontrar o que você busca.

Para criar um índice simples:

tarefas.create_index("titulo")

Para garantir que um campo seja único (por exemplo, impedir tarefas duplicadas):

tarefas.create_index("titulo", unique=True)

Com o unique=True, qualquer tentativa de inserir um documento com um título que já existe vai gerar um erro DuplicateKeyError. Você pode tratar isso no código:

from pymongo.errors import DuplicateKeyError

try:
    tarefas.insert_one({"titulo": "Estudar PyMongo", "concluida": False})
except DuplicateKeyError:
    print("Tarefa com esse titulo ja existe.")

Exemplo prático: CRUD completo com rotas Flask

Agora vamos juntar tudo em uma aplicação Flask funcional. Este exemplo implementa um CRUD completo para uma coleção de tarefas:

from flask import Flask, request, jsonify
from pymongo import MongoClient
from pymongo.errors import DuplicateKeyError
from bson.objectid import ObjectId

app = Flask(__name__)

client = MongoClient("mongodb://localhost:27017/")
db = client["flask_app"]
tarefas = db["tarefas"]
tarefas.create_index("titulo", unique=True)


def serializar(doc):
    doc["_id"] = str(doc["_id"])
    return doc


@app.route("/tarefas", methods=["POST"])
def criar_tarefa():
    dados = request.get_json()
    try:
        resultado = tarefas.insert_one({
            "titulo": dados["titulo"],
            "concluida": False
        })
    except DuplicateKeyError:
        return jsonify({"erro": "Tarefa ja existe"}), 409
    return jsonify({"id": str(resultado.inserted_id)}), 201


@app.route("/tarefas", methods=["GET"])
def listar_tarefas():
    filtro = {}
    status = request.args.get("concluida")
    if status is not None:
        filtro["concluida"] = status.lower() == "true"
    docs = tarefas.find(filtro)
    return jsonify([serializar(doc) for doc in docs])


@app.route("/tarefas/<id>", methods=["GET"])
def buscar_tarefa(id):
    doc = tarefas.find_one({"_id": ObjectId(id)})
    if not doc:
        return jsonify({"erro": "Tarefa nao encontrada"}), 404
    return jsonify(serializar(doc))


@app.route("/tarefas/<id>", methods=["PUT"])
def atualizar_tarefa(id):
    dados = request.get_json()
    campos = {}
    if "titulo" in dados:
        campos["titulo"] = dados["titulo"]
    if "concluida" in dados:
        campos["concluida"] = dados["concluida"]
    resultado = tarefas.update_one(
        {"_id": ObjectId(id)},
        {"$set": campos}
    )
    if resultado.matched_count == 0:
        return jsonify({"erro": "Tarefa nao encontrada"}), 404
    return jsonify({"modificados": resultado.modified_count})


@app.route("/tarefas/<id>", methods=["DELETE"])
def deletar_tarefa(id):
    resultado = tarefas.delete_one({"_id": ObjectId(id)})
    if resultado.deleted_count == 0:
        return jsonify({"erro": "Tarefa nao encontrada"}), 404
    return jsonify({"removidos": resultado.deleted_count})

Para testar, rode o servidor com flask run e use curl ou qualquer cliente HTTP:

# Criar tarefa
curl -X POST http://localhost:5000/tarefas \
  -H "Content-Type: application/json" \
  -d '{"titulo": "Aprender MongoDB"}'

# Listar todas
curl http://localhost:5000/tarefas

# Filtrar por status
curl http://localhost:5000/tarefas?concluida=false

# Atualizar
curl -X PUT http://localhost:5000/tarefas/<ID> \
  -H "Content-Type: application/json" \
  -d '{"concluida": true}'

# Deletar
curl -X DELETE http://localhost:5000/tarefas/<ID>

Com esse exemplo, você tem uma API REST completa usando Flask e MongoDB. A partir daqui, você pode adicionar validação de dados, paginação nas listagens e autenticação nas rotas.

Continue lendo

Compartilhar