Getting started
As we talked about before, we will be creating API's using the FastAPI framework for Python. Now we are going to take our first steps.
Installation
Let's install FastAPI including all optional dependencies and features:
$ pip install "fastapi[all]"
...that also includes uvicorn
, that you can use as the server that runs your code.
Note
You can also install it part by part.
This is what you would probably do once you want to deploy your application to production:
pip install fastapi
Also install uvicorn
to work as the server:
pip install "uvicorn[standard]"
And the same for each of the optional dependencies that you want to use.
First Steps
The simplest FastAPI file could look like this:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
Copy that to a file main.py
.
Run the live server:
$ uvicorn main:app --reload
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [28720]
INFO: Started server process [28722]
INFO: Waiting for application startup.
INFO: Application startup complete.
Uvicorn command
The command 'uvicorn main:app' refers to:
- main: the file 'main.py' (the Python "module").
- app: the object created inside of
main.py
with the lineapp = FastAPI()
. - --reload: make the server restart after code changes. Only use for development.
In the output, there's a line with something like:
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
That line shows the URL where your app is being served, in your local machine. Open your browser at http://127.0.0.1:8000.
You will see the JSON response as:
{"message": "Hello World"}
Interactive API docs
Now go to http://127.0.0.1:8000/docs.
You will see the automatic interactive API documentation (provided by Swagger UI):
OpenAPI
FastAPI generates a "schema" with all your API using the OpenAPI standard for defining APIs. A "schema" is a definition or description of something. Not the code that implements it, but just an abstract description:
- API "schema" In this case, OpenAPI is a specification that dictates how to define a schema of your API. This schema definition includes your API paths, the possible parameters they take, etc.
- Data "schema" The term "schema" might also refer to the shape of some data, like a JSON content. In that case, it would mean the JSON attributes, and data types they have, etc.
In essence, OpenAPI defines an API schema for your API. And that schema includes definitions (or "schemas") of the data sent and received by your API using JSON data schemas.
What is OpenAPI for ?
The OpenAPI schema is what powers the interactive documentation system included. And there are dozens of alternatives, all based on OpenAPI. You could easily add any of those alternatives to your application built with FastAPI. You could also use it to generate code automatically, for clients that communicate with your API. For example, frontend, mobile or IoT applications.
Check the openapi.json
If you are curious about how the raw OpenAPI schema looks like, FastAPI automatically generates a JSON (schema) with the descriptions of all your API.
You can see it directly at: http://127.0.0.1:8000/openapi.json.
It will show a JSON starting with something like:
{
"openapi":"3.0.2",
"info":{
"title":"FastAPI",
"version":"0.1.0"
},
"paths":{
"/":{
"get":{
"summary":"Root",
"operationId":"root__get",
"responses":{
"200":{
"description":"Successful Response",
"content":{
"application/json":{
"schema":{
}
}
}
}
}
}
}
}
}
A Hello-world API, step by step
We will be creating our first API in 5 general steps, learning along the way:
- Import
FastAPI
- Create an instance of the
app
- Write a path operation decorator, like
@app.get("/")
- Write a path operation function, like
def root(): ...
above - Run the development server, like
uvicorn main:app --reload
FastAPI
Step 1: Import from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
FastAPI
is a Python class that provides all the functionality for your API.
FastAPI
app instance
Step 2: Create a from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
Here the app
variable will be an "instance" of the class FastAPI
. This will be the main point of interaction to create all your API. This app
is the same one referred by uvicorn
in the command:
$ uvicorn main:app --reload
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
In other words, if you create your app as such:
from fastapi import FastAPI
my_awesome_api = FastAPI()
@my_awesome_api.get("/")
async def root():
return {"message": "Hello World"}
And put it in a file main.py
, then you would call uvicorn
like:
$ uvicorn main:my_awesome_api --reload
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
Step 3: Create a path operation
With path operation we refer to a combination of a path and an HTTP operation.
Theoretical background
"Path" here refers to the last part of the URL starting from the first /
.
So, in a URL like:
https://example.com/items/foo
...the path would be:
/items/foo
Endpoints?
A "path" is also commonly called an "endpoint" or a "route".
"Operation" here refers to one of the HTTP "methods". One of:
POST
GET
PUT
PATCH
DELETE
...and the more exotic ones:
OPTIONS
HEAD
TRACE
In the HTTP protocol, you can communicate to each path using one (or more) of these "methods". In OpenAPI, each of the HTTP methods is called an "operation".
When building APIs, you normally use these specific HTTP methods to perform a specific action:
POST
: to create data.GET
: to read data.PUT
: to update data.DELETE
: to delete data.
Define an @decorator for a path operation
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
The @app.get("/")
is a Python decorator which tells FastAPI that the function right below is in charge of handling requests that go to:
- the path
/
- using an HTTP
GET
operation
You can also use the other operations:
@app.post()
@app.put()
@app.patch()
@app.delete()
For example the @app.put("/home")
would be a Python decorator which tells FastAPI that the function right below it is in charge of handling requests that go to:
- the path
/home
- using an HTTP
PUT
operation
What is this `@decorator` ?
That @something
syntax in Python is called a "decorator". You put it on top of a function. Like a pretty decorative hat (I guess that's where the term came from). A "decorator" takes the function below and does something with it. In our case, this decorator tells FastAPI that the function below corresponds to the path /
with an operation get
. It is the "path operation decorator".
Step 4: Define the path operation function
This is our path operation function:
- path: is
/
. - operation: is
GET
. - function: is the function below the "@decorator", i.e. below
@app.get("/")
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
This is a simple Python function. Here it will be called by FastAPI whenever it receives a request to the URL /
using a GET
operation. In this case, it is an async
function.
You could also define it as a normal function instead of async def
:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def root():
return {"message": "Hello World"}
More information about the difference between synchronous and asynchronous is given later on in the course.
For now the function is filled out with a return of a simple JSON object.
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
You can return a dict
, list
, singular values as str
, int
, etc. You can also return Pydantic models (you'll learn about that later).
Step 5: Run the development server
$ uvicorn main:app --reload
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
Try out the API!
Recap
So we have done the following to create the most basic API:
- Import
FastAPI
- Create an instance of the
app
- Write a path operation decorator, like
@app.get("/")
- Write a path operation function, like
def root(): ...
above - Run the development server, like
uvicorn main:app --reload