I am trying to set Optional
some params in a PUT method from my API.
Using fastAPI
and mongodb
I’ve build a simple API to insert students and delete the ones, now I am looking to allow me update the entries but not mandatory “params”.
I’ve checked this Fastapi: put method and looks like something I am looking for mongodb.
And this response from art049 looks similar what I already have in my @api_router.put('/update-student/{id}', tags=['Student'])
MongoDb with FastAPI
As example for my question here I have this structure:
Models:
class Student(BaseModel): age:int name:str address:str class UpdateStudent(BaseModel): age: Optional[int] = None name: Optional[str] = None address: Optional[str] = None
Schemas:
def serializeDict(a) -> dict: return {**{i:str(a[i]) for i in a if i=='_id'},**{i:a[i] for i in a if i!='_id'}} def serializeList(entity) -> list: return [serializeDict(a) for a in entity]
Routes:
@api_router.post('/create-student', tags=['Students']) async def create_students(student: Student): client.collegedb.students_collection.insert_one(dict(student)) return serializeList(client.collegedb.students_collection.find())
Also I know I can update the entry without problems in this way:
@api_router.put('/update-student/{id}', tags=['Student']) async def update_student(id,ustudent: UpdateStudent): client.collegedb.students_collection.find_one_and_update({"_id":ObjectId(id)},{ "$set":dict(ustudent) }) return serializeDict(client.collegedb.students_collection.find_one({"_id":ObjectId(id)}))
My problem as you can see with my Models I need a way to validate which params are modified and update the ones only: If right now I Update for example the age only; since the other params are not required, name and address will be stored as None (null actually) because I set this in my model.
Maybe I can do something like this:
if ustudent.age != None: students_collection[ObjectId(id)] = ustudent.age if ustudent.name != None: students_collection[ObjectId(id)] = ustudent.name if ustudent.address != None: students_collection[ObjectId(id)] = ustudent.address
I know I can use this in a simple dictionary but never tried before in a collection in mongodb since pydantic not support ObjectId for iterations and that’s why serializeDict
was created.
I will really appreciate if somebody can give a hint with my concern
Advertisement
Answer
You can use exclude_unset=True
argument as suggested in FastAPI documentation:
@api_router.put('/update-student/{id}', tags=['Student']) async def update_student(id,ustudent: UpdateStudent): client.collegedb.students_collection.find_one_and_update({"_id":ObjectId(id)},{ "$set":ustudent.dict(exclude_unset=True) }) return serializeDict(client.collegedb.students_collection.find_one({"_id":ObjectId(id)}))
Here is the documentation for exporting Pydantic models.