# Como integrar validação de CPF em Django com views assíncronas

> Aprenda a integrar validação de CPF em tempo real em Django usando views assíncronas e a API da CPFHub.io com exemplos completos.

**Publicado:** 13/06/2026
**Autor:** Redação CPFHub.io
**URL:** https://cpfhub.io/blog/como-integrar-validacao-de-cpf-em-django-com-views-assincronas

---

O **Django 4.1+** introduziu suporte nativo a views assíncronas, permitindo que aplicações Python realizem chamadas a APIs externas sem bloquear o servidor. Para integrar a API de CPF da CPFHub.io, você define uma `async def` view que chama um serviço assíncrono com `httpx.AsyncClient` — o Django detecta automaticamente que se trata de uma view assíncrona e a executa no event loop. A API responde em ~900ms, autentica via header `x-api-key` e cobra R$0,15 por consulta excedente ao plano sem bloquear requisições.

---

## 1. Pré-requisitos

* **Python 3.10+** e **Django 4.2+** instalados.

* O pacote `httpx` para requisições HTTP assíncronas: `pip install httpx`.

* Um servidor ASGI como **Uvicorn** ou **Daphne** para rodar views assíncronas.

* Uma conta gratuita na [**CPFHub.io**](https://www.cpfhub.io/)

---

## 2. Configure as variáveis de ambiente

Nunca exponha sua chave de API diretamente no código. Use variáveis de ambiente ou um arquivo `.env` com o pacote `python-decouple`:

```bash
pip install python-decouple
```

Crie um arquivo `.env` na raiz do projeto:

```env
CPFHUB_API_KEY=SUA_CHAVE_DE_API
CPFHUB_BASE_URL=https://api.cpfhub.io
CPFHUB_TIMEOUT=5
```

No `settings.py`, importe as configurações:

```python
from decouple import config

CPFHUB_API_KEY = config("CPFHUB_API_KEY")
CPFHUB_BASE_URL = config("CPFHUB_BASE_URL", default="https://api.cpfhub.io")
CPFHUB_TIMEOUT = config("CPFHUB_TIMEOUT", default=5, cast=int)
```

---

## 3. Crie o serviço assíncrono de consulta

Crie um módulo `services.py` dentro do seu app Django para encapsular a lógica de comunicação com a API:

```python
# myapp/services.py
import httpx
import re
from django.conf import settings

class CpfHubError(Exception):
 """Exceção personalizada para erros da API CPFHub."""
 def __init__(self, message: str, status_code: int = None):
 self.message = message
 self.status_code = status_code
 super().__init__(self.message)

async def consultar_cpf(cpf: str) -> dict:
 """
 Consulta dados de um CPF na API da CPFHub.io de forma assíncrona.
 """
 cpf_limpo = re.sub(r"\D", "", cpf)

 if len(cpf_limpo) != 11:
 raise CpfHubError("CPF deve conter exatamente 11 dígitos", status_code=400)

 url = f"{settings.CPFHUB_BASE_URL}/cpf/{cpf_limpo}"
 headers = {
 "x-api-key": settings.CPFHUB_API_KEY,
 "Accept": "application/json",
 }

 async with httpx.AsyncClient(timeout=settings.CPFHUB_TIMEOUT) as client:
 try:
 response = await client.get(url, headers=headers)
 except httpx.TimeoutException:
 raise CpfHubError("Timeout ao consultar a API da CPFHub", status_code=504)
 except httpx.RequestError as e:
 raise CpfHubError(f"Erro de conexão: {str(e)}", status_code=502)

 if response.status_code == 200:
 data = response.json()
 if data.get("success"):
 return data["data"]
 raise CpfHubError("Resposta inesperada da API", status_code=500)
 elif response.status_code == 400:
 raise CpfHubError("CPF com formato inválido", status_code=400)
 elif response.status_code == 401:
 raise CpfHubError("Chave de API inválida ou ausente", status_code=401)
 elif response.status_code == 404:
 raise CpfHubError("CPF não encontrado na base de dados", status_code=404)
 else:
 raise CpfHubError(f"Erro inesperado: HTTP {response.status_code}", status_code=response.status_code)
```

---

## 4. Crie a view assíncrona

Com Django 4.1+, basta definir a view como uma função `async def`. O framework detecta automaticamente que se trata de uma view assíncrona:

```python
# myapp/views.py
import json
from django.http import JsonResponse
from .services import consultar_cpf, CpfHubError

async def consulta_cpf_view(request, cpf: str):
 """
 View assíncrona para consulta de CPF via API da CPFHub.io.
 Método: GET /api/cpf/<cpf>/
 """
 if request.method != "GET":
 return JsonResponse(
 {"error": "Método não permitido"},
 status=405,
 )

 try:
 dados = await consultar_cpf(cpf)
 return JsonResponse({
 "success": True,
 "data": dados,
 })
 except CpfHubError as e:
 return JsonResponse(
 {"success": False, "error": e.message},
 status=e.status_code or 500,
 )
 except Exception:
 return JsonResponse(
 {"success": False, "error": "Erro interno do servidor"},
 status=500,
 )
```

---

## 5. Configure as URLs

Adicione a rota no `urls.py` do app:

```python
# myapp/urls.py
from django.urls import path
from . import views

urlpatterns = [
 path("api/cpf/<str:cpf>/", views.consulta_cpf_view, name="consulta_cpf"),
]
```

E inclua no `urls.py` principal do projeto:

```python
# project/urls.py
from django.urls import path, include

urlpatterns = [
 path("", include("myapp.urls")),
]
```

---

## 6. Configure o servidor ASGI

Views assíncronas no Django exigem um servidor ASGI. Configure o `asgi.py` do projeto:

```python
# project/asgi.py
import os
from django.core.asgi import get_asgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
application = get_asgi_application()
```

Inicie o servidor com Uvicorn:

```bash
pip install uvicorn
uvicorn project.asgi:application --host 0.0.0.0 --port 8000 --workers 4
```

---

## 7. Teste a integração

Faça uma requisição de teste usando cURL:

```bash
curl -X GET http://localhost:8000/api/cpf/12345678900/
```

A resposta esperada:

```json
{
 "success": true,
 "data": {
 "cpf": "12345678900",
 "name": "João da Silva",
 "nameUpper": "JOÃO DA SILVA",
 "gender": "M",
 "birthDate": "15/06/1990",
 "day": 15,
 "month": 6,
 "year": 1990
 }
}
```

---

## 8. Integração com formulários Django

Se você deseja validar CPF em um formulário HTML, crie um formulário com validação assíncrona no frontend:

```python
# myapp/forms.py
from django import forms
import re

class CpfForm(forms.Form):
 cpf = forms.CharField(
 max_length=14,
 label="CPF",
 widget=forms.TextInput(attrs={
 "placeholder": "000.000.000-00",
 "class": "form-control",
 }),
 )

 def clean_cpf(self):
 cpf = self.cleaned_data["cpf"]
 cpf_limpo = re.sub(r"\D", "", cpf)
 if len(cpf_limpo) != 11:
 raise forms.ValidationError("CPF deve conter 11 dígitos.")
 return cpf_limpo
```

```python
# myapp/views.py (view adicional para formulário)
from django.shortcuts import render
from .forms import CpfForm
from .services import consultar_cpf, CpfHubError

async def formulario_cpf_view(request):
 resultado = None
 erro = None

 if request.method == "POST":
 form = CpfForm(request.POST)
 if form.is_valid():
 try:
 resultado = await consultar_cpf(form.cleaned_data["cpf"])
 except CpfHubError as e:
 erro = e.message
 else:
 form = CpfForm()

 return render(request, "myapp/consulta_cpf.html", {
 "form": form,
 "resultado": resultado,
 "erro": erro,
 })
```

---

## 9. Boas práticas

* **Timeout** — Sempre configure timeout nas requisições HTTP. O valor padrão de 5 segundos é adequado, considerando que a API da CPFHub responde em ~900ms.

* **Servidor ASGI** — Views assíncronas só trazem benefício real quando executadas em um servidor ASGI como Uvicorn ou Daphne. Com WSGI, o Django executa a view assíncrona em uma thread separada, anulando o ganho. A [documentação oficial do Django](https://docs.djangoproject.com/en/stable/topics/async/) detalha o comportamento em cada modo.

* **Reutilização de client** — Para alto volume de requisições, considere criar um `httpx.AsyncClient` como singleton em vez de instanciar um novo a cada chamada.

* **Rate limiting local** — Implemente um controle de taxa no seu lado para evitar consumir cota desnecessariamente, especialmente no plano gratuito com 50 consultas/mês.

* **Cache** — Use o cache do Django para armazenar resultados de consultas recentes e evitar chamadas duplicadas.

* **Segurança** — Nunca exponha a chave de API no frontend. Todas as chamadas à CPFHub devem ser feitas pelo backend.

* **LGPD** — A API da CPFHub.io opera em conformidade com a LGPD. Garanta que sua aplicação também trate dados pessoais de acordo com a legislação vigente.

---

## Perguntas frequentes

### Por que usar views assíncronas no Django para consultar a API de CPF?

Views assíncronas permitem que o servidor Django atenda outras requisições enquanto aguarda a resposta da API externa — que leva ~900ms. Com um servidor ASGI como Uvicorn, isso se traduz em maior throughput sem aumentar o número de workers. Para endpoints de consulta de CPF, onde o gargalo é sempre o I/O de rede, a abordagem assíncrona reduz o tempo ocioso dos processos do servidor.

### Qual a diferença entre rodar a view assíncrona com ASGI versus WSGI?

Com ASGI (Uvicorn, Daphne), a view executa no event loop e libera o worker durante a espera pela API — o comportamento esperado. Com WSGI (Gunicorn clássico), o Django detecta a corrotina e a executa em uma thread separada usando `asyncio.run()`, o que bloqueia o worker e anula o ganho de performance. Para aproveitar views assíncronas de verdade, ASGI não é opcional.

### A API CPFHub.io bloqueia quando o limite do plano gratuito é atingido?

Não. Ao atingir as 50 consultas gratuitas do mês, a API continua respondendo normalmente e cobra R$0,15 por consulta excedente — sem retornar erro nem bloquear. Para evitar gastos inesperados, implemente cache no Django para reutilizar resultados recentes e monitore o consumo pelo painel em `app.cpfhub.io/settings/billing`.

### Como garantir conformidade com a LGPD ao consultar CPF via Django?

Use o CPF apenas para a finalidade declarada ao titular, armazene apenas o necessário e implemente controle de acesso aos logs de consulta. A [ANPD](https://www.gov.br/anpd) orienta que dados de identificação devem ser tratados com o princípio da necessidade. Documente a base legal para o tratamento e configure TTL curto no cache para não reter dados além do necessário.

---

### Leia também

- [Como validar CPF no frontend com React e API REST](https://cpfhub.io/blog/como-validar-cpf-no-frontend-com-react-e-api-rest)
- [Como consumir API de CPF usando Django e Django REST Framework](https://cpfhub.io/blog/como-consumir-api-cpf-django-rest-framework)
- [Como consumir API de CPF em Python com FastAPI](https://cpfhub.io/blog/como-consumir-api-de-cpf-em-python-com-fastapi)
- [Boas práticas para consumir APIs de CPF de forma segura](https://cpfhub.io/blog/boas-praticas-consumir-apis-cpf-segura)

---

## Conclusão

Integrar a API da [**CPFHub.io**](https://www.cpfhub.io/)

Cadastre-se em [cpfhub.io](https://www.cpfhub.io/)

