端点中的 FastAPI 冲突路径参数 - 好的做法?

FastAPI conflict path parameter in endpoint - good practices?

我正在使用 FastAPI 为资源 student 创建 2 个 GET 方法。我希望通过两种方式获得 student:通过 student_id 或通过 student_name.

问题是,我最初按如下方式创建了 2 个端点

@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

问题是端点名称相互冲突,它都是 /student 后跟一个参数,只有其中一个可以工作 - 在这种情况下只能 /student/{student_name} 因为它是定义在前面。所以我通过在端点名称中添加更多内容来想出这个简单的解决方法:

@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

我在 get_student)by_id 方法的端点名称中添加了 /byid。虽然现在两个端点都可以工作,但我想知道这是否被认为是一种好的做法?当需要使用单个路径参数查询一个资源以区分端点名称时,最佳做法是什么?

我会做这样的事情

@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()

有了这个,您的代码将对未来的更改更加开放,我只会在按 id 搜索时使用 url 参数,任何其他搜索条件都可以使用查询参数作为过滤器参数处理