Reputation: 4035
I want to make a query parameter required depending of another query parameter in FastApi
For example I have four query parameters: command
, start_date
, end_date
and increment
If command
is equal to "analyse", then end_date
must be required. But if command
is equal to "add_working_days" then end_date
is not required but increment
is required. Is this possible?
This is my code righ now:
import datetime
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/api/")
async def read_item(
start_date: str = Query(..., regex=r"[\d]{4}-[\d]{1,2}-[\d]{1,2}"),
end_date: str = Query(..., regex=r"[\d]{4}-[\d]{1,2}-[\d]{1,2}"),
command: str = None,
increment: int = None,
):
parsed_start_date = datetime.datetime.strptime(start_date, "%Y-%m-%d")
parsed_end_date = datetime.datetime.strptime(end_date, "%Y-%m-%d")
duration = parsed_end_date - parsed_start_date
return duration.days
Upvotes: 6
Views: 8112
Reputation: 3497
What you want to do is possible if you write it like you suggest. You can set default None values to parameters to allow some flexibility with and do the validation of rules like:
If command == analyse:
Check start_date is valid
Check end_date is also valid
Check increment is None
If command == add_working_days:
Check start_date is valid
Check end_date is None
Check increment is also valid
But my opinion is that this is not the proper way to do what you want.
In the above case FastAPI cannot generate documentation that express your parameters combinations in GUI (e.g. https://petstore.swagger.io/)
My opinion is that
Such documentation is your product to any consumers of your API. It will not be clear to them which combination of parameters should be passed together. You will need to provide such documentation as free text in the description.
Since Open API specification was created to help developers understand each other as quick as possible, I suggest you stick to the spec and avoid such rules combinations.
FastAPI's syntax which derives from the Open API specification will not be able to describe URLs that route the behavior of your code to a different function, based on the parameters you choose to pass.
Maybe, Maybe, Maybe if this was Java, maybe Swagger like tools could support your code, since multiple signatures can be written for the same function name, but since this is Python I don't see this as a viable behavior.
-- My Suggestion
Follow the answer of Nguyễn Nhân. As he suggested describe the different URLs and parameters combinations as separate router methods. This will save you the need to design complex IFs. This will clarify to your users that they must pass such and such parameters.
Disclaimer
All the above is what I think is the right way. Others may disagree. If I have to consider one case where I would use one URL to do it all, it would be a case where each optional parameter adds to the expected functionality and is not dependent on any other parameters.
for example:
domain/maps?location=XYZ&
add_markers: boolean
add_traffic: boolean
language: [EN,HE]
etc.
where possible links are
domain/maps?location=XYZ&add_markers=true&add_traffic=true&language=EN
domain/maps?location=XYZ&add_traffic=true&language=HE
domain/maps?location=XYZ&add_markers=true
etc., where each passed parameter is independent of the others.
Upvotes: 3
Reputation: 311
I recommend to separate your api
import datetime
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/api/analyse")
async def read_item_for_analyse(
start_date: str = Query(..., regex=r"[\d]{4}-[\d]{1,2}-[\d]{1,2}"),
end_date: str = Query(..., regex=r"[\d]{4}-[\d]{1,2}-[\d]{1,2}"),
increment: int = None,
):
# do something
@app.get("/api/add_working_days")
async def read_item_for_add_working_days(
start_date: str = Query(..., regex=r"[\d]{4}-[\d]{1,2}-[\d]{1,2}"),
end_date: str = None,
increment: int = Query(..., title="Increase working days"),
):
# do something
It's clear and easy to understand, or continue with your style and add some "if...else" is enough.
Upvotes: 4