Instalação do FastAPI (bash)
Criação do ambiente virtual
Criar um diretório para o código
bash
mkdir projeto
# cria um diretório para o projeto
cd projeto
# acessa o diretório criado
Criar o ambiente virtual usando o módulo venv do Python
bash
python -m venv .venv
# cria o ambiente virtual no diretório oculto .venv
Ativar o ambiente virtual
bash
source .venv/bin/activate
Instalação do pacote FastAPI
No ambiente virtual ativo:
bash
pip install "fastapi[standard]"
Estrutura exemplar em FastAPI
Criar um arquivo main.py
python
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
Execute o servidor
bash
fastapi dev
Conferir
- Abra o navegador em http://127.0.0.1:8000/
- A resposta em JSON deverá ser
{"message": "Hello World"}
Implementar endpoints básicos (CRUD)
routers/locais.py
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from app.database import SessionLocal
from app.schemas.local import LocalCreate
from app.services import locais_service
router = APIRouter(prefix="/locais", tags=["Locais"])
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@router.post("/")
def criar(local: LocalCreate, db: Session = Depends(get_db)):
return locais_service.criar_local(
db,
local.nome,
local.latitude,
local.longitude
)
@router.get("/")
def listar(db: Session = Depends(get_db)):
return locais_service.listar_locais(db)
@router.get("/{id}")
def buscar(id: int, db: Session = Depends(get_db)):
local = locais_service.buscar_local(db, id)
if not local:
raise HTTPException(status_code=404, detail="Local não encontrado")
return local
@router.put("/{id}")
def atualizar(id: int, local: LocalCreate, db: Session = Depends(get_db)):
atualizado = locais_service.atualizar_local(
db,
id,
local.nome,
local.latitude,
local.longitude
)
if not atualizado:
raise HTTPException(status_code=404, detail="Local não encontrado")
return atualizado
@router.delete("/{id}")
def deletar(id: int, db: Session = Depends(get_db)):
removido = locais_service.deletar_local(db, id)
if not removido:
raise HTTPException(status_code=404, detail="Local não encontrado")
return {"message": "Local removido com sucesso"}
services/locais_service.py
from sqlalchemy.orm import Session
from app.models.local import Local
from geoalchemy2.shape import from_shape
from shapely.geometry import Point
def criar_local(db: Session, nome: str, lat: float, lon: float):
ponto = from_shape(Point(lon, lat), srid=4326)
local = Local(nome=nome, geom=ponto)
db.add(local)
db.commit()
db.refresh(local)
return local
def listar_locais(db: Session):
return db.query(Local).all()
def buscar_local(db: Session, id: int):
return db.query(Local).filter(Local.id == id).first()
def atualizar_local(db: Session, id: int, nome: str, lat: float, lon: float):
local = db.query(Local).filter(Local.id == id).first()
if not local:
return None
local.nome = nome
local.geom = from_shape(Point(lon, lat), srid=4326)
db.commit()
db.refresh(local)
return local
def deletar_local(db: Session, id: int):
local = db.query(Local).filter(Local.id == id).first()
if not local:
return None
db.delete(local)
db.commit()
return True
Integrar com banco de dados PostgreSQL
Instalar dependências
pip install sqlalchemy psycopg2-binary geoalchemy2
````
### database.py
```python
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
DATABASE_URL = "postgresql://postgres:senha@localhost:5432/gis"
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(
autocommit=False,
autoflush=False,
bind=engine
)
models/base.py
from sqlalchemy.orm import declarative_base
Base = declarative_base()
models/local.py
from sqlalchemy import Column, Integer, String
from geoalchemy2 import Geometry
from app.models.base import Base
class Local(Base):
__tablename__ = "locais"
id = Column(Integer, primary_key=True, index=True)
nome = Column(String, nullable=False)
geom = Column(Geometry("POINT", srid=4326))
Criar tabelas no banco
from app.database import engine
from app.models.base import Base
from app.models import local
Base.metadata.create_all(bind=engine)
Usar sessão no FastAPI
from app.database import SessionLocal
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
Testar conexão
from app.database import engine
with engine.connect() as conn:
print("Conectado com sucesso")
Validar dados de entrada com Pydantic
schemas/local.py
from pydantic import BaseModel, Field
class LocalBase(BaseModel):
nome: str = Field(..., min_length=2, max_length=100)
class LocalCreate(LocalBase):
latitude: float = Field(..., ge=-90, le=90)
longitude: float = Field(..., ge=-180, le=180)
class LocalUpdate(BaseModel):
nome: str | None = Field(None, min_length=2, max_length=100)
latitude: float | None = Field(None, ge=-90, le=90)
longitude: float | None = Field(None, ge=-180, le=180)
class LocalResponse(LocalBase):
id: int
class Config:
orm_mode = True
````
### Uso nos endpoints
```python id="xq4x7s"
from app.schemas.local import LocalCreate, LocalUpdate
@router.post("/")
def criar(local: LocalCreate, db: Session = Depends(get_db)):
return locais_service.criar_local(
db,
local.nome,
local.latitude,
local.longitude
)
@router.put("/{id}")
def atualizar(id: int, local: LocalUpdate, db: Session = Depends(get_db)):
return locais_service.atualizar_local(
db,
id,
local.nome,
local.latitude,
local.longitude
)
Exemplo de requisição válida
```json id="uk1gqk" { "nome": "Brasília", "latitude": -15.7942, "longitude": -47.8825 }
## Testar endpoints via Swagger UI
### Executar a aplicação
```bash
uvicorn app.main:app --reload
````
### Acessar Swagger UI
Abra no navegador:
http://localhost:8000/docs
### Acessar documentação alternativa
http://localhost:8000/redoc
### Testar endpoints
Na interface do Swagger:
* Clique em um endpoint (ex: POST /locais)
* Clique em "Try it out"
* Preencha o corpo da requisição
* Clique em "Execute"
### Exemplo de teste (POST /locais)
```json
{
"nome": "Brasília",
"latitude": -15.7942,
"longitude": -47.8825
}
Ver resposta
- Código HTTP (200, 201, 404, etc.)
- Corpo da resposta
- Tempo de execução
Testar outros endpoints
- GET /locais → lista todos
- GET /locais/{id} → busca por id
- PUT /locais/{id} → atualiza
- DELETE /locais/{id} → remove
Documentar uso da API
Base URL
http://localhost:8000
````
## Endpoints
### Criar local
```http
POST /locais
Corpo da requisição:
{
"nome": "Brasília",
"latitude": -15.7942,
"longitude": -47.8825
}
Resposta:
{
"id": 1,
"nome": "Brasília"
}
Listar locais
GET /locais
Resposta:
[
{
"id": 1,
"nome": "Brasília"
}
]
Buscar local por ID
GET /locais/{id}
Exemplo:
GET /locais/1
Resposta:
{
"id": 1,
"nome": "Brasília"
}
Atualizar local
PUT /locais/{id}
Exemplo:
PUT /locais/1
Corpo da requisição:
{
"nome": "Brasília Atualizada",
"latitude": -15.80,
"longitude": -47.90
}
Resposta:
{
"id": 1,
"nome": "Brasília Atualizada"
}
Remover local
DELETE /locais/{id}
Exemplo:
DELETE /locais/1
Resposta:
{
"message": "Local removido com sucesso"
}
Códigos de resposta
- 200 OK: requisição bem-sucedida
- 201 Created: recurso criado
- 404 Not Found: recurso não encontrado
- 422 Unprocessable Entity: erro de validação