i have a fast api and i'm trying to model my input data, as shown below. i want to define the data class such that , the colleges is a list , but optional , a person may or may not have college experience and within this list, there is a classes list which is optional. i have included a optional keyword , such that even if the input is missing these values , the call to my api doesn't fail. is this the right way to design my classes . also , is there a better/short way to design my classes in pydantic for nested model classes ? person -> colleges , then colleges have classes , a nested structure. can one define entire structure in a single class vs having to define three classes?
{
'name': 'john',
'Colleges': [
{
'name': 'Harvard',
...
'Classes': [
{
'level': 'graduate',
'grade': 'A'
},
{
'level': 'graduate',
'grade': 'B'
}
]
}
]
}
# Import required modules
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import List
# Create a FastAPI app instance
app = FastAPI()
class Class(BaseModel):
level: str
grade: int
class College(BaseModel):
name: str
age: int
Classes: optional[List[Class]]= None
class Person(BaseModel):
name: str
description: str
Colleges: Optional[List[College]] = None
@app.post("/create/", response_model=dict)
def create(person: Person):
//do somethign
return {'message': 'success'}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000)
Your implementation is mostly correct. While, nesting directly in one class may be possible, but it's less readable and harder to manage as your structure grows.
It's not recommended for readability and maintainability. However, here's how it could be done:
class Person(BaseModel):
name: str
description: Optional[str] = None
colleges: Optional[List[dict]] = None
This sacrifices the benefit of strong type-checking and validation provided by Pydantic's nested models. If you need to access nested properties in your API logic, you lose auto-completion and validation benefits.
However, there are a few corrections and improvements that can make the code cleaner and more concise:
from fastapi import FastAPI
from pydantic import BaseModel
from typing import List, Optional
# Create a FastAPI app instance
app = FastAPI()
# Define nested Pydantic models
class Class(BaseModel):
level: str
grade: str # Grade should be a string (e.g., 'A', 'B')
class College(BaseModel):
name: str
age: int
classes: Optional[List[Class]] = None # Use lowercase for JSON-friendly field names
class Person(BaseModel):
name: str
description: Optional[str] = None
colleges: Optional[List[College]] = None # Use lowercase for JSON-friendly field names
@app.post("/create/", response_model=dict)
def create(person: Person):
# Do something with the input
return {'message': 'success'}
classes
, colleges
) instead of Classes
, Colleges
.optional[List[Class]]
to Optional[List[Class]]
. (typo in optional
)str
instead of int
('A'
, 'B'
).description
are handled properly with Optional
.