Skip to content
Advertisement

Set Optional params in PUT method using fastAPI/mongodb

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.

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement