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

问题描述 投票:0回答:4

我正在使用 FastAPI 为资源创建 2 个 GET 方法。我希望通过 2 种方式获得

student
:通过
student
或通过
student_id
问题是,我最初创建了 2 个端点,如下

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/{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

添加到

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

python rest backend fastapi endpoint
4个回答
3
投票

get_student)by_id

将这些“转换器”添加到您的路径中将根据指定类型将您的请求路由到正确的端点:)

我能够在 Starlette 中找到这方面的文档,我不太熟悉,但 FastAPI 是建立在它之上的。

https://www.starlette.io/routing/


0
投票

@app.get("/student/{student_name:str}", response_model=schemas.Student, status_code=200) def get_student_by_name(student_name: str, db: Session = Depends(get_db)): ... @app.get("/student/{student_id:int}", response_model=schemas.Student, status_code=200) def get_student_by_id(student_id: int, db: Session = Depends(get_db)): ...

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


0
投票

如果我想确保与要移植到 FastAPI 的 Web 框架的兼容性,并且它显示了原始行为,那么我可以通过一种方法来复制它。

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

https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/

FastAPI 强调输入和文档,这对我来说是有意义的,相同的路径前缀应该智能地路由到更具体的、可转换的,特别是如果更具体的优先的话。

如果我可以放弃更强大的文档和验证,我可以像这样涵盖两个基础:

@app.get("/student/{student_id}",
         response_model=schemas.Student,
         status_code=200)
def get_student_by_id(
        student_id: int = Path(
            title="The ID of the student to get"),
        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
...


@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

https://fastapi.tiangolo.com/tutorial/path-params/#path-convertor

用于验证参数是否为 int 或学生姓名的现有逻辑,然后验证这些逻辑或返回适当的错误。我看你已经有了这个逻辑,所以这不是最大的缺点。

我最初经常使用这种方法。了解了所包含的 OpenAPI 文档的价值后,我更喜欢单独的功能。有时维护网站链接会更好。例如,WordPress 可以同时在

@app.get("/student/{student_name_or_id}",
         response_model=schemas.Student,
         status_code=200)
async def get_student(
        student_name_or_id: str = Path(
            title="The ID or name of the student to get"),
        db: Session = Depends(get_db)):
    if student_name_or_id.isdigit():
        db_student = crud.get_student_by_id(db, int(student_name_or_id))
    else:
        db_student = crud.get_student_by_name(db, student_name_or_id)
    if db_student is None:
        raise HTTPException(status_code=404, detail="Student not found")
    return db_student

int

提供页面,一个使用日期,另一个使用类别和 slug。

    
您可以使用查询参数来仅使用一个路径来区分student_id和student_name,这是达到相同目的的更简洁的方式,例如:


0
投票

然后,您可以通过运行 if 语句来根据查询参数提供请求的数据,如下所示:

/python/faster-fastapi

希望这有帮助

	

© www.soinside.com 2019 - 2024. All rights reserved.