1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
19 small wins to finish your pathNext lesson →
Request bodies: POST with a Pydantic model
Parameters suit an id or an option. A new ticket is a whole record, so it travels in the request body as JSON, and a Pydantic model says what that JSON must contain.
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
TICKETS = []
class NewTicket(BaseModel):
customer: str
text: str
@app.post("/tickets")
def create_ticket(ticket: NewTicket):
record = {"id": len(TICKETS) + 1, **ticket.model_dump()}
TICKETS.append(record)
return recordA parameter whose type is a Pydantic model is read from the body. FastAPI reads the JSON, builds a NewTicket from it, and only then calls your function. TICKETS is a list in memory, so it starts empty each time the app starts.
from fastapi.testclient import TestClient
from tickets import app
client = TestClient(app)
response = client.post("/tickets", json={"customer": "Asha", "text": "I was charged twice"})
print(response.status_code)
print(response.json())A body missing a field
response = client.post("/tickets", json={"customer": "Ben"})
print(response.status_code)
print(response.json())422 again, this time with loc pointing into the body at text, and input showing what was actually sent. The client learns exactly what to fix, and your function never has to check.
Extra fields
response = client.post("/tickets", json={"customer": "Chen", "text": "Refund please", "admin": True})
print(response.json())admin is not in the model, so it is dropped silently. A client cannot slip a field into your record by sending it.
Try it yourself
- Add
priority: int = 3toNewTicketand post a ticket with and without it. - Post
{"customer": 5, "text": "hi"}. Is a number accepted as a string? - Post two tickets and check the second one's id.
Little by little, you're building something great.