Query Parameters¶
It is very common to simply want to declare some query parameters in your controllers. Sometimes those are also used as filters for a given search or simply extra parameters in general.
What are query parameters in Esmerald?¶
Query parameters are those parameters that are not part of the path parameters and therefore those are automatically
injected as query
parameters for you.
from esmerald import Esmerald, Gateway, JSONResponse, get
fake_users = [{"last_name": "Doe", "email": "john.doe@example.com"}]
@get("/users")
async def read_user(skip: int = 1, limit: int = 5) -> JSONResponse:
return fake_users[skip : skip + limit]
app = Esmerald(
routes=[
Gateway(read_user),
]
)
As you can see, the query is a key-pair value that goes after the ?
in the URL and seperated by a &
.
Applying the previous example, it would look like this:
http://127.0.0.1/users?skip=1&limit=5
The previous url will be translated as the following query_params
:
skip
: with a value of 1.limit
: with a value of 5.
Since they are an integral part of the URL, it will automatically populate the parameters of the function that corresponds each value.
Declaring defaults¶
Query parameters are not by design, part of a fixed URL path and that also means they can assume the following:
- They can have defaults, like
skip=1
andlimit=5
. - They can be
optional
.
In the previous example, the URL had already defaults for skip
and limit
and the corresponding typing as per requirement
of Esmerald but what if we want to make them optional?
There are different ways of achieving that, using the Optional
or Union
.
Tip
from Python 3.10+ the Union
can be replaced with |
syntax.
from typing import Optional
from esmerald import Esmerald, Gateway, JSONResponse, get
@get("/users/{id}")
async def read_user(id: int, q: Optional[int] = None) -> JSONResponse: ...
app = Esmerald(
routes=[
Gateway(read_user),
]
)
from typing import Union
from esmerald import Esmerald, Gateway, JSONResponse, get
@get("/users/{id}")
async def read_user(id: int, q: Union[int, None] = None) -> JSONResponse: ...
app = Esmerald(
routes=[
Gateway(read_user),
]
)
Check
Esmerald is intelligent enough to understand what is a query param
and what is a path param
.
Now we can call the URL and ignore the q
or call it when needed, like this:
Without query params
http://127.0.0.1/users/1
With query params
http://127.0.0.1/users/1?q=searchValue
Query and Path parameters¶
Since Esmerald is intelligent enough to distinguish path parameters and query parameters automatically, that also means you can have multiple of both combined.
Warning
You can't have a query and path parameters with the same name as in the end, it is still Python parameters being declared in a function.
from esmerald import Esmerald, Gateway, JSONResponse, get
@get("/users/{id}/{last_name}")
async def read_user(id: int, last_name: str, skip: int = 1, limit: int = 5) -> JSONResponse: ...
app = Esmerald(
routes=[
Gateway(read_user),
]
)
Required parameters¶
When you declare a query parameter
without a default and without being optional when you call the URL
it will raise an error of missing value for the corresponding.
from esmerald import Esmerald, Gateway, JSONResponse, get
@get("/users")
async def read_user(limit: int) -> JSONResponse: ...
app = Esmerald(
routes=[
Gateway(read_user),
]
)
If you call the URL like this:
http://127.0.0.1/users
It will raise an error of missing value, something like this:
{
"detail": "Validation failed for <URL> with method GET.",
"errors": [
{
"type": "int_type",
"loc": [
"limit"
],
"msg": "Input should be a valid integer",
"input": null,
"url": "https://errors.pydantic.dev/2.8/v/int_type"
}
]
}
Which means, you need to call with the declared parameter, like this, for example:
http://127.0.0.1/users?limit=10
Extra with Esmerald params¶
Because everything in Esmerald just works you can also add restrictions and limits to your query parameters. For example.
you might want to add a limit into the size of a string q
when searching not to exceed an X value.
from typing import Union
from esmerald import Esmerald, Gateway, JSONResponse, Query, get
@get("/users")
async def read_user(q: str = Query(max_length=10)) -> JSONResponse: ...
app = Esmerald(
routes=[
Gateway(read_user),
]
)
This basically tells that a q
query parameters must not exceed the length of 10
of an exception will be raised.