FastAPI offers us two main options to specify what data we want: as part of the path or as query parameters. In this post we expand on our minimalistic example and dig a bit deeper into the basic concepts of FastAPI.
This post is part of my journey to learn Python. You find the code for this post in my PythonFriday repository on GitHub.
Query parameters
We can append our query parameters to the URL with this pattern:
1 |
?valueA=1&valueB=Hello |
The query starts with a ? and then follow the variables with their values, separated by a &.
We can add this little method to our main.py file to experiment with the query parameters:
1 2 3 4 5 |
from fastapi import FastAPI, Request, @app.get("/echo") async def echo(request: Request): return request.query_params |
If we access the URL http://localhost:8000/echo?a=1&b=Hello, we should see something like this:
You can play with it and add more variables and you should get immediate feedback.
A more explicit usage of query parameters
If we want to create a small calculation function that creates the sum of the variables a, b, and c, we can write the function like this:
1 2 3 |
@app.get("/calculator") async def calculate(a, b, c): return a + b + c |
If we now go to http://localhost:8000/calculator?a=1&b=2&c=3, we get a result back that may not be what we expected:
The result is 123, then by default everything we get into FastAPI is a string. We could go and convert the values like this:
1 2 3 4 5 6 |
@app.get("/calculator") async def calculate(a, b, c): a = int(a) b = int(b) c = int(c) return {"value": a + b + c} |
However, while that works, it is much easier to use type hints:
1 2 3 |
@app.get("/calculator") async def calculate(a: int, b: int, c: int): return {"value": a + b + c} |
Whatever you choose, if you go back to the API, you now should get the correct result:
Path parameters
The other option we can use to influence the results we get is a path parameter. For that we define our path and add {} around the parameters, like we would with f-strings:
1 2 3 |
@app.get("/weather/{city}") async def weather(city): return {"city": city} |
We can now call our weather endpoint with the name of the city or a postal code, then FastAPI again interprets the parameter as a string:
If we want our parameter to be something else than a string, we need to specify it:
1 2 3 |
@app.get("/weather/{city}") async def weather(city: int): return {"city": city} |
If we run it now with a string while we expect an integer, we get an error:
While type hints for python are hints, with FastAPI those hints are turned into checks and the parameters are validated against them. That gives us an input check for free.
Next
Type hints allow us to get the data that we want from the path and query parameters. If we are explicit on what we expect, we do not need to make the conversation by ourselves. Instead, FastAPI delegates this task to Pydantic and throws errors if the types do not match.
Next week we try something new and send data to FastAPI.