In this post, we will learn how to perform FastAPI Query Parameter validation. In particular, we will look into the use of Query function that allows us to perform validations in a declarative manner.
If you are not aware of query parameters in FastAPI, you can check out this detailed post about FastAPI Query Parameters. Also, if you are new to FastAPI, you can refer to this detailed post about getting started with FastAPI.
- 1 – The Simple Query Parameter
- 2 – Query Parameter Length Validation
- 3 – Query Parameter Validation for Minimum Length
- 4 – Regex Validation
- 5 – Query Parameter Default Value
- 6 – Mandatory Query Parameter
- 7 – Query Parameter List Value
- 8 – Query Parameter Additional Metadata
- 9 – Query Parameter Alias
- Conclusion
1 – The Simple Query Parameter
Let’s start with a basic example.
from fastapi import FastAPI
from typing import Optional
app = FastAPI()
@app.get("/books")
def read_books(test: Optional[str] = None):
results = {"books": [{"book_name": "The Great Hunt"}, {"book_name": "The Dragon Reborn"}]}
if test:
results.update({"test": test})
return results
Here, the query parameter test is of type Optional[str]. Basically, this means that the data type is str. However, it could also be None. Specifying None means that it is not a mandatory field.
2 – Query Parameter Length Validation
Let us now add another validation. We would like to validate the max length of the query parameter test.
We can do it as below:
from fastapi import FastAPI, Query
from typing import Optional
app = FastAPI()
@app.get("/books")
def read_books(test: Optional[str] = Query(None, max_length=10)):
results = {"books": [{"book_name": "The Great Hunt"}, {"book_name": "The Dragon Reborn"}]}
if test:
results.update({"test": test})
return results
Here, we use the Query function imported from fastapi. The Query(none) keeps the parameter as optional just like before. The additional property max_length specifies the maximum length of the parameter.
This will validate the data and show a clear error message if the value of test exceeds 10 characters. See below:
{
"detail": [{
"loc": ["query", "test"],
"msg": "ensure this value has at most 10 characters",
"type": "value_error.any_str.max_length",
"ctx": {
"limit_value": 10
}
}]
}
3 – Query Parameter Validation for Minimum Length
We can also add a check or validation for minimum length of the query parameter test.
See below:
@app.get("/books")
def read_books(test: Optional[str] = Query(None, min_length=3, max_length=10)):
results = {"books": [{"book_name": "The Great Hunt"}, {"book_name": "The Dragon Reborn"}]}
if test:
results.update({"test": test})
return results
If the min length check is violated, we get the below error response.
{
"detail": [{
"loc": ["query", "test"],
"msg": "ensure this value has at least 3 characters",
"type": "value_error.any_str.min_length",
"ctx": {
"limit_value": 3
}
}]
}
4 – Regex Validation
We can also validate using a Regex or Regular Expression.
@app.get("/books")
def read_books(test: Optional[str] = Query(None, min_length=3, max_length=10, regex="^testquery$")):
results = {"books": [{"book_name": "The Great Hunt"}, {"book_name": "The Dragon Reborn"}]}
if test:
results.update({"test": test})
return results
Basically, in the above snippet, error response is triggered if the query parameter has value other than testquery.
5 – Query Parameter Default Value
Just like we pass None as the first argument to the Query function, we can also pass an actual default value.
See below example:
@app.get("/books")
def read_books(test: Optional[str] = Query("testquery", min_length=3, max_length=10)):
results = {"books": [{"book_name": "The Great Hunt"}, {"book_name": "The Dragon Reborn"}]}
if test:
results.update({"test": test})
return results
In this case, if we don’t supply an actual value, FastAPI will use the default value for the query parameter.
6 – Mandatory Query Parameter
We can also make the query parameter test as mandatory by not declaring a default value.
See below example:
@app.get("/books")
def read_books(test: Optional[str] = Query(..., min_length=3, max_length=10)):
results = {"books": [{"book_name": "The Great Hunt"}, {"book_name": "The Dragon Reborn"}]}
if test:
results.update({"test": test})
return results
Here, instead of a default value, we use three dots (…). Basically, this signifies that the query parameter is mandatory.
In case we don’t provide a valid value, we get the below error response.
{
"detail": [{
"loc": ["query", "test"],
"msg": "field required",
"type": "value_error.missing"
}]
}
7 – Query Parameter List Value
Another use case with query parameters is to be able to process a list of values. In other words, multiple values.
As an example, let’s consider we want to pass the below values for the query parameter test.
http://localhost:8000/items/?test=query1&test=query2
To achieve this, we have to tweak our Query function to accept a list. See below example:
from fastapi import FastAPI, Query
from typing import List, Optional
app = FastAPI()
@app.get("/books")
def read_books(test: Optional[List[str]] = Query(None)):
results = {"books": [{"book_name": "The Great Hunt"}, {"book_name": "The Dragon Reborn"}]}
if test:
results.update({"test": test})
return results
Also, we can supply default values for list query parameters as below:
@app.get("/books")
def read_books(test: Optional[List[str]] = Query(["query1", "query2"])):
results = {"books": [{"book_name": "The Great Hunt"}, {"book_name": "The Dragon Reborn"}]}
if test:
results.update({"test": test})
return results
8 – Query Parameter Additional Metadata
We can also add more metadata about a parameter.
See below example:
@app.get("/books")
def read_books(test: Optional[str] = Query(None, title="Query string", description="Description of Query String", min_length=3)):
results = {"books": [{"book_name": "The Great Hunt"}, {"book_name": "The Dragon Reborn"}]}
if test:
results.update({"test": test})
return results
Here, we have added a title and description property. The same will also be reflected in the interactive API docs as below.
9 – Query Parameter Alias
This is another useful feature.
Consider that we wish to call our query parameter test-query. However, test-query is not a valid python variable name. But we have a hard requirement to have our query parameter named as test-query only.
In such a case, we can use the alias property as below:
@app.get("/books")
def read_books(test: Optional[str] = Query(None, alias="test-query")):
results = {"books": [{"book_name": "The Great Hunt"}, {"book_name": "The Dragon Reborn"}]}
if test:
results.update({"test": test})
return results
Conclusion
With this, we have learnt how to perform FastAPI Query Parameter validation using Query function. We looked at various options available as part of the Query function to declaratively provide validations.
If you have any comments or queries, please do mention in the comments section below.
0 Comments