I am creating 2 GET methods for a resource student
using FastAPI. I'm looking to GET a student
in 2 ways: by student_id
or by student_name
.
The issue is that, I initially created the 2 endpoints as follows
@app.get("/student/{student_name}", response_model=schemas.Student, status_code=200)
def get_student_by_name(student_name: str, db: Session = Depends(get_db)):
db_student = crud.get_student_by_name(db, student_name)
if db_student is None:
raise HTTPException(status_code=404, detail="Student not found")
return db_student
@app.get("/student/{student_id}", response_model=schemas.Student, status_code=200)
def get_student_by_id(student_id: int, db: Session = Depends(get_db)):
db_student = crud.get_student_by_id(db, student_id)
if db_student is None:
raise HTTPException(status_code=404, detail="Student not found")
return db_student
The problem is that the endpoint names are conflicting with each other, it is both /student
followed by a parameter and only one of them could work - in this case only /student/{student_name}
because it is defined in the front. So I came up with this simple workaround by adding a bit more to the endpoint names:
@app.get("/student/{student_name}", response_model=schemas.Student, status_code=200)
def get_student_by_name(student_name: str, db: Session = Depends(get_db)):
db_student = crud.get_student_by_name(db, student_name)
if db_student is None:
raise HTTPException(status_code=404, detail="Student not found")
return db_student
@app.get("/student/byid/{student_id}", response_model=schemas.Student, status_code=200)
def get_student_by_id(student_id: int, db: Session = Depends(get_db)):
db_student = crud.get_student_by_id(db, student_id)
if db_student is None:
raise HTTPException(status_code=404, detail="Student not found")
return db_student
I added /byid
to the endpoint name of the get_student)by_id
method. While both endpoints could work now, I am wondering if this is considered a good practice? WHat would be the best practice when one resource needed to be queried with a single path parameter to differentiate the endpoint names?
I will do something like this
@app.get("/student/{student_id}", response_model=schemas.Student, status_code=200)
def get_student(student_id: str, db: Session = Depends(get_db)):
db_student = crud.get_student_by_id(db, student_id)
if db_student is None:
raise HTTPException(status_code=404, detail="Student not found")
return db_student
# use search criterias as query params
@app.get("/student/", response_model=List[schemas.Student], status_code=200)
def get_students(student_name: string = None, db: Session = Depends(get_db)):
# Query inside your crud file
query = db.query(Student)
if student_name:
# if you want to search similar items
query = query.filter(Student.name.like(f"%{student_name}%"))
# if you want to search an exact match
query = query.filter(Student.name == student_name)
return query.all()
With this your code will be a little bit more open to future changes, I will only use a url param when searching by id, any other search criteria can be handled as a filter parameter using query params