HTTPException and response models
Lesson 5 ended with a crash for a ticket that does not exist. An API should say not found, with a 404, and should never send fields the caller has no business seeing.
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
app = FastAPI()
TICKETS = {1: {"id": 1, "customer": "Asha", "text": "I was charged twice", "notes": "VIP"}}
class TicketOut(BaseModel):
id: int
customer: str
text: str
@app.get("/tickets/{ticket_id}", response_model=TicketOut)
def get_ticket(ticket_id: int):
if ticket_id not in TICKETS:
raise HTTPException(status_code=404, detail="ticket not found")
return TICKETS[ticket_id]raise HTTPException(status_code=404, ...) stops the function and sends that status with detail as the body. It is the raise from the Python course, and FastAPI turns it into a response instead of a crash.
response_model=TicketOut passes whatever the function returns through TicketOut before sending it. The stored ticket has a private notes field; the model does not, so it is left out.
from fastapi.testclient import TestClient
from tickets import app
client = TestClient(app)
for ticket_id in (1, 9):
response = client.get(f"/tickets/{ticket_id}")
print(response.status_code, response.json())The 404 is now a decision your code made, with a message a client can show. And VIP never left the service.
Choosing the status code
A POST that creates something should answer 201, created. Pass it in the decorator: @app.post("/tickets", status_code=201). The status code is part of what your API promises, so clients can check it without reading the body.
The API describes itself
schema = app.openapi()
print(list(schema["paths"]))
print(list(schema["paths"]["/tickets/{ticket_id}"]["get"]["responses"]))FastAPI builds an OpenAPI description of every endpoint from your code: paths, parameters, models and responses. 422 is listed because a path parameter can fail validation. Lesson 8 shows the page it generates from this.
- Remove
response_model=TicketOutand fetch ticket 1 again. - Raise
HTTPException(status_code=403, detail="not your ticket")for ticket 1. - Add
status_code=201to a POST endpoint from lesson 6 and check the status.
You understood something today that you didn't yesterday.