API Django REST: Upload e Retorno de Arquivo Excel

Construir um endpoint DRF que aceita uploads de Excel e retorna um Excel processado exige lidar com dados de formulário multipart, lê-los com pandas, transformá-los e devolver o arquivo de saída na resposta. Cada um desses passos tem seu próprio modo de falhar.

TL;DR: Construa uma API Django REST Framework que aceita upload de arquivo Excel, processa as linhas com pandas e retorna um novo arquivo Excel na resposta.
Stack: Python, Django, Django REST Framework, pandas, openpyxl
Nível: Intermediário
Tempo de leitura: ~7 min

A view

A view cuida de todo o pipeline: valida o arquivo enviado, salva temporariamente, lê com pd.read_excel(), transforma as linhas, escreve um novo Excel e retorna como FileResponse.

import os
import pandas as pd
from django.conf import settings
from django.http import FileResponse
from rest_framework.views import APIView
from rest_framework.response import Response
from .serializers import FileUploadSerializer
from django.core.files.storage import default_storage
from .protocols import MeuExtractorRequest

class MeuExtractorView(APIView):
    def post(self, request, format=None):
        itens_solicitados = []
        serializer = FileUploadSerializer(data=request.data)

        if serializer.is_valid():
            file = serializer.validated_data['file']
            file_path = default_storage.save(file.name, file)

            try:
                data = pd.read_excel(file_path)

                for index, row in data.iterrows():
                    item = MeuExtractorRequest()
                    item.titulo = row['titulo']
                    item.ano = row['ano']
                    itens_solicitados.append(item.__dict__)

                new_data = pd.DataFrame(itens_solicitados)
                output_path = os.path.join(settings.BASE_DIR, 'output.xlsx')
                new_data.to_excel(output_path, index=False)

                return FileResponse(
                    open(output_path, 'rb'),
                    content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
                )
            except Exception as e:
                return Response({'error': str(e)}, status=400)

        return Response(serializer.errors, status=400)

Serializer

from rest_framework import serializers

class FileUploadSerializer(serializers.Serializer):
    file = serializers.FileField()

Modelo de dados

class MeuExtractorRequest:
    titulo: str
    ano: str

O que você construiu

Um endpoint DRF completo que aceita upload de Excel, transforma cada linha usando um modelo tipado, constrói um novo DataFrame e devolve o Excel resultante como resposta para download.

Próximos passos

  • Limpe os arquivos enviados temporariamente após a resposta para não encher o disco do servidor ao longo do tempo.
  • Adicione validação no nível do pandas: verifique se as colunas necessárias existem antes de processar as linhas.
  • Para arquivos grandes, processe as linhas de forma assíncrona com Celery e retorne um ID de tarefa para o cliente fazer polling em vez de esperar uma requisição HTTP longa.

Dúvidas ou feedback? Me encontre no LinkedIn ou GitHub.

Deixe um comentário