Introduction to FastAPI

How to set up a FastAPI Project

Resources

Welcome to an Introduction to FastAPI. In this article, I'll show you how to build a social media REST API that allows users to register, authenticate, post updates, and leave comments. Then we'll deploy the API and make it available to the public!

This tutorial is a bit different from the official tutorial in that it doesn't cover every feature of FastAPI. The aim of this tutorial is to get you building a real project, rather than show you everything that can be done. I believe that by building a real project, you'll retain much more information. Then when you want to add more features, you'll be able to research how to do it using FastAPI.

However, it's a good idea to read the official tutorial in addition to this one. By reading both, you'll build a real project and get insight into the major features of the framework. Which one you read first is up to you, I don't think it matters.

How to set up a new FastAPI project

The first thing to do when starting a new project is to create a virtual environment for it. I use pyenv to manage my Python versions, so I'd first select which Python version I'm going to use, and then create a virtual environment:

$ pyenv local 3.11.0
$ pyenv exec python -m venv .venv
$ source .venv/bin/activate  # different on windows

First, install the required libraries. Create a file called requirements.txt and add these two lines to it:

fastapi
uvicorn[standard]

Then install them:

$ pip install -r requirements.txt

Now let's create a file for our project. Name it main.py, and place the following code inside it:

main.py
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello, world!"}

This is very similar to how a Flask app starts, if you're familiar with that. You import the FastAPI class, and create your app variable. Then, you define individual endpoints and functions that will run when the endpoint is accessed.

Using the decorator @app.get("/") we've specified that when we run our app and access the / endpoint, the root function should run.

When this runs and returns a dictionary, FastAPI will turn it into JSON for us. So at the end of the day, we should get back some JSON containing {"message": "Hello, world!"}.

Let's run the app with:

$ uvicorn main:app --reload

Here uvicorn is the program, main is the Python file, app is the Python variable that contains the FastAPI object. Using the --reload flag means that when we make code changes to either main.py or any file that is imported (directly or indirectly) by main.py, the server will restart.

You can press CTRL+C to quit the uvicorn server at any time. Then you'd have to re-run the command to start the app again.

If we access http://127.0.0.1:8000 you should see the JSON response:

{"message": "Hello, world!"}

Important to note, JSON is pure text. While our app returned a Python dictionary, FastAPI then turns the dictionary into text and sends that to the browser. If we wanted to include things in the JSON that aren't easily convertible to text, we may struggle. More on that later!

At this point you can also check out the autogenerated documentation. It's quite empty to start with, but as we build our API, the documentation will tell us what the API does, what data it requires from users, and what it returns. There are two options for autogenerated documentations, either at /docs or at /redoc.

Running FastAPI on Repl.it

To help you try out FastAPI quicker, without having to set it up locally, here's an online IDE that you can use (using repl.it).

To edit and run the app, you will need a repl.it account. More information on repl.it here.

Caution

When the repl.it app runs, it gets a unique URL. You can see it when you run the app, in the top part of the screen. In my case, it's https://FastAPI-Starter.tecladocode.repl.co. Also, the port number must be 8080 instead of the FastAPI default which is 8000.

Tip

In future lectures I'll include a repl.it link in the resources section (at the top of the page) rather than embedding it.