Reputation: 445
I'd like to have two path operations with the same path @app.get("/movies/", ..)
:
@app.get("/movies/", response_model=schemas.Movie)
def read_movie_by_title(title: str, db: Session = Depends(get_db)):
db_movie = crud.get_movie_by_title(db, title=title)
return db_movie
@app.get("/movies/", response_model=List[schemas.Movie])
def read_movies(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
db_movies = crud.get_movies(db, skip=skip, limit=limit)
return db_movies
As You can see, the first one is for getting a movie by its title and has a query parameter (title
) and the second one is for getting a list. When I check the generated docs, the one for read_movie_by_title
is missing.
I tried to solve this by changing the path for read_movie_by_title
to /movies
by removing /
, but I don't like this solution at all.
So the question is: Is there a way to have two equal paths, but one with query parameters, or do I need to do this in a different way? Any suggestions?
Upvotes: 0
Views: 76
Reputation: 1281
The answer to your question (Is there a way to have two equal paths, but one with query parameters) is no, the only way to differentiate a path is by its method (GET, PUT, POST, DELETE, ...
).
You do however have multiple ways of achieving your desired result.
The standard REST
approach to this would be to define a different path for the title based retrieval, such as /movies/{title}
, like in the first example shown in the documentation for path parameters @ FastAPI.
If you want to implement a search
feature instead of a direct retrieval by unique title
method, you can do something like this:
@app.get("/movies", response_model=List[schemas.Movie])
def read_movies(title: Optional[str] = None, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
# list of filters
filters = []
if title: # if it's not none
filters.append(models.Movie.title.ilike(f"%{title}%"))
db_movies = crud.get_movies(db, filters=filters, skip=skip, limit=limit)
return db_movies
and within your crud operation you would query it something like:
return session.query(models.Movie).filter(*filters).all()
@app.get("/movies", response_model=List[schemas.Movie])
def read_movies(title: Optional[str] = None, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
if title: # if it's not none
return crud.get_movie_by_title(db, title=title)
return crud.get_movies(db, filters=filters, skip=skip, limit=limit)
Though the latter might confuse the consumer of your API, hence the REST
approach will be the most recommended one.
Upvotes: 0
Reputation: 15987
You could use Path Parameters instead of Query parameters for the first one, by changing the endpoint to "/movies/{title}"
:
@app.get("/movies/{title}", response_model=schemas.Movie)
def read_movie_by_title(title: str, db: Session = Depends(get_db)):
db_movie = crud.get_movie_by_title(db, title=title)
return db_movie
# 2nd remains the same
@app.get("/movies/", response_model=List[schemas.Movie])
def read_movies(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
db_movies = crud.get_movies(db, skip=skip, limit=limit)
return db_movies
Upvotes: 1