FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints. It is designed to be easy to use and to make building APIs fast and efficient.
In this tutorial, we will guide you through building a simple API using FastAPI. We will cover setting up FastAPI, creating routes, handling requests, and responses, as well as integrating with databases and other external services.
Setting up FastAPI:
To get started with FastAPI, you first need to install it using pip:
pip install fastapi
You also need to install an ASGI server, such as uvicorn, to run your FastAPI application:
pip install uvicorn
Creating a FastAPI application:
To create a new FastAPI application, you need to define an instance of the FastAPI class and add routes to it. Routes are defined using Python decorators.
Here’s an example of a simple FastAPI application:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
In this example, we define a new FastAPI application and add a single route that returns a JSON response with a "Hello World" message when the root URL is accessed.
Running the FastAPI application:
To run your FastAPI application, you can use the uvicorn command-line tool. Run the following command in your terminal:
uvicorn main:app --reload
This command tells uvicorn to run the FastAPI application defined in a file named "main.py" and to reload the server automatically when the code changes.
Accessing the API:
Once you have your FastAPI application running, you can access the API by visiting http://127.0.0.1:8000 in your web browser. You should see the "Hello World" message displayed on the page.
Handling requests and responses:
FastAPI provides several decorators for handling different types of HTTP requests, such as POST, PUT, DELETE, etc. You can use these decorators to define routes that accept and respond to different types of requests.
Here’s an example of a POST route that accepts JSON data and returns a JSON response:
from fastapi import FastAPI, Request
app = FastAPI()
@app.post("/items/")
async def create_item(request: Request):
data = await request.json()
return {"item": data}
In this example, we define a new POST route that accepts JSON data from the request body and returns it as part of the response. The route uses the @app.post
decorator to specify that it should be called when a POST request is made to the "/items/" URL.
Integrating with databases:
FastAPI makes it easy to integrate with databases using asynchronous programming with Python’s asyncio
module. You can use popular ORMs like SQLAlchemy and databases like PostgreSQL, MySQL, SQLite, etc., with FastAPI to build powerful APIs that interact with databases.
Here’s an example of integrating FastAPI with SQLAlchemy to create a simple API that interacts with a SQLite database:
Install SQLAlchemy and databases package:
pip install sqlalchemy databases
Create a new SQLAlchemy engine and database URL:
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
Define a data model and a database table:
from sqlalchemy import Column, Integer, String
class Item(Base):
__tablename__ = "items"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, index=True)
description = Column(String)
Create the database table:
Base.metadata.create_all(bind=engine)
Create routes to interact with the database:
from fastapi import FastAPI, HTTPException
from sqlalchemy.orm import Session
from typing import List
app = FastAPI()
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.post("/items/")
async def create_item(item: Item, db: Session = Depends(get_db)):
db.add(item)
db.commit()
return item
@app.get("/items/", response_model=List[Item])
async def read_items(skip: int = 0, limit: int = 10, db: Session = Depends(get_db)):
items = db.query(Item).offset(skip).limit(limit).all()
return items
In this example, we define two routes, one for creating a new item in the database and one for retrieving a list of items from the database. The routes use a Session
dependency to manage the database connections.
Conclusion:
In this tutorial, we have covered the basics of building APIs with FastAPI, including setting up FastAPI, creating routes, handling requests, and responses, and integrating with databases. FastAPI is a powerful and efficient web framework for building APIs with Python, and it offers many features that make it easy to build high-performance APIs quickly and easily. I hope this tutorial has been helpful in getting you started with FastAPI and building your own APIs. Happy coding!
Where did you set the authentication method?
Long happy days of life!
Thanks.
Hi Tim! please bring a video to make DB connection in FastAPI using SQLITE. Creating multiple users, authenticating and authorizing them! would be very grateful! 🙂
48:17 here we can directly write inventory[item] = item and this will return the updated value
Hey Tim – very well structured. Thank you! Is there a github repo for the code? That would be a lot easier than typing it in and then resolving typos.💚
Such an underrated video
26:23 Wish I could have seen what you were writing….. Great video but things like this are super frustrating.
Not sure if this will help but for 25:00 I ran into a long error when using None inside of the Path function. if you remove it and just use the description it worked for me. Love the tutorials tim!
Thank You Tim ,Great video I like the way how you used dictionary first then introduced classes
The file surface_area_sq_km.tsv contains data on the surface area, in km2
, of all countries
in the world, while the file forest_coverage_percent.tsv holds information on the forest
coverage percentage of these countries in the years 2009 and 2019. In these files, values
are separated by tabs (which are represented by a special character "t") and the first
row is a header. Countries appear by the same order in both files. Define the function
forest_coverage. This function takes as arguments the name of files, reads them and
returns a dictionary containing all countries and is structured as follows:
{ (…),
"Angola": {
"area": 1250000.0,
2009: {"coverage_percentage": 58.3, "coverage": 728750.0},
2019: {"coverage_percentage": 53.9, "coverage": 673750.0},
"growth": -7.55
}, (…),
"Gibraltar": {
"area": 10.0,
2009: {"coverage_percentage": 0.0, "coverage": 0.0},
2019: {"coverage_percentage": 0.0, 'coverage": 0.0},
"growth": "-"
}, (…) }
The "coverage" key represents the forested area in km2 computed from the "area"
and the "coverage_percentage". "growth" is the percentage of growth of forested
area since 2009 rounded to 2 decimal places. Note that all numbers in this exercise are
of float type (excluding year values).
Note: in case the forested area of a country in 2009 is 0.0, growth should be "-".
It is a nice tutorial. Thank you
Great Video Tim
"Hey everyone! I just wanted to share my experience with different code editors. I've tried various IDEs, including VS Code and Visual Studio,
and I ran into some issues that were frustrating to deal with. so its best to use sublime text like in the video
So in simple words, FastAPI it allows communication of the Backend with the Frontend? I understand correct?
lt and GT can you show the line u typed
I am running this examples on IDLE shell 3.10.2 and it always get this error: ModuleNotFoundError: No module named 'fastapi'. could you tell me what is wrong?. Thanks in advance
To finally fix def get_item(…) put the following as the function body:
if item_id not in inventory:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Item ID not found.")
return inventory[item_id]
By this there will be no server error anymore.
A little update for those watching in 2023, and have version 0.101.1, if you get the error "AssertionError: Path parameters cannot have a default value" when doing the Path, change None for …
It should look like this:
def get_item(item_id:int = Path(…,description="The id of the item.")):
if you have a problem with the update function try below code
def create_item(item_id: int, item: UpdateItem):
if item_id not in inventory:
return {'Error': 'item does not exist'
inventory[item_id].__dict__.update(item.dict(exclude_unset=True))
return inventory[item_id]
I am getting an error – AssertionError: Path parameters cannot have a default value for this line – def get_item(item_id: int = Path(None, description= "The ID of the item you would like to view")):
Tim, you're the best at what you do.
Please, keep it up because we need you.