- Published on
Getting Started with FastAPI
- Authors
- Name
- Wuttichai Kaewlomsap
- @wuttichaihung
- Name
- MarchGPT
1. Introduction
FastAPI is a modern, fast (high-performance) web framework for building APIs with Python 3.7+ based on standard Python type hints. It is designed to be easy to use and to provide high performance out-of-the-box. FastAPI is built on top of the Starlette framework for the web parts and Pydantic for the data parts. Here are some key features of FastAPI:
- High performance: FastAPI is built on top of Starlette, an ASGI (Asynchronous Server Gateway Interface) framework, which allows for high performance and asynchronous execution.
- Fast development: FastAPI provides automatic generation of OpenAPI and JSON Schema documentation, as well as automatic data validation, which speeds up development time.
- Easy to use: FastAPI is designed to be easy to use, with a simple syntax for defining endpoints and models.
- Standards-based: FastAPI is built on top of industry-standard tools such as Pydantic for data validation and type hints, and is fully compliant with the OpenAPI standard.
- Supports async/await: FastAPI fully supports asynchronous programming using Python's async/await syntax, allowing for efficient and non-blocking I/O operations.
In this blog post, we will explore how to create a simple FastAPI application, including the folder hierarchy, code for main.py, Dockerfile, schema.py, models.py, crud.py, and how to connect to SQLite.
2. The simplest FastAPI app
main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
run_fastapi.sh
uvicorn main:app --reload
Code on Github
3. The common FastAPI appFolder Hierarchy
getting-started-with-fastapi/
├── app/
│ ├── __init__.py
│ ├── crud.py
│ ├── database.py
│ ├── main.py
│ ├── models.py
│ └── schemas.py
├── Dockerfile
└── requirements.txt
Here's a brief explanation of what each file and folder is for:
app
: This folder contains the main FastAPI application code, including the main.py file, which defines the application instance and routes, and the routers folder, which contains the route handlers.app/__init__.py
: This file makes the app directory a Python package.app/crud.py
: This file defines the CRUD (Create, Read, Update, Delete) operations for the application.app/database.py
: This file contains the code to connect to the SQLite database.app/main.py
: This file defines the FastAPI application instance and routes.app/models.py
: This file defines the Pydantic models used in the application.app/schemas.py
: This file defines the Pydantic schemas used in the application.Dockerfile
: This file defines the Docker image for the application.requirements.txt
: This file specifies the Python dependencies for the application.
main.py
app/main.py
from fastapi import FastAPI, Depends
from app.database import engine, SessionLocal
from app import models, schemas, crud
from sqlalchemy.orm import Session
app = FastAPI()
models.Base.metadata.create_all(bind=engine)
# Dependency
def get_db():
try:
db = SessionLocal()
yield db
finally:
db.close()
# create item
@app.post("/items/")
def create_item(item: schemas.ItemCreate, db: Session = Depends(get_db)):
return crud.create_item(db=db, item=item)
# get item by id
@app.get("/items/{item_id}")
def read_item(item_id: int, db: Session = Depends(get_db)):
return crud.get_item(db=db, item_id=item_id)
# update item
@app.put("/items/{item_id}")
def update_item(item_id: int, item: schemas.ItemUpdate, db: Session = Depends(get_db)):
return crud.update_item(db=db, item_id=item_id, item=item)
# delete item
@app.delete("/items/{item_id}")
def delete_item(item_id: int, db: Session = Depends(get_db)):
return crud.delete_item(db=db, item_id=item_id)
database.py
app/database.py
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()
schemas.py
app/schemas.py
from pydantic import BaseModel
class ItemBase(BaseModel):
title: str
description: str = None
class ItemCreate(ItemBase):
pass
class ItemUpdate(ItemBase):
pass
class Item(ItemBase):
id: int
class Config:
orm_mode = True
models.py
app/models.py
from sqlalchemy import Boolean, Column, ForeignKey, Integer, String
from sqlalchemy.orm import relationship
from .database import Base
class Item(Base):
__tablename__ = "items"
id = Column(Integer, primary_key=True, index=True)
title = Column(String, index=True)
description = Column(String, index=True)
crud.py
app/crud.py
from sqlalchemy.orm import Session
from app import models, schemas
def create_item(db: Session, item: schemas.ItemCreate):
db_item = models.Item(title=item.title, description=item.description)
db.add(db_item)
db.commit()
db.refresh(db_item)
return db_item
def get_item(db: Session, item_id: int):
return db.query(models.Item).filter(models.Item.id == item_id).first()
def update_item(db: Session, item_id: int, item: schemas.ItemUpdate):
db_item = db.query(models.Item).filter(models.Item.id == item_id).first()
db_item.title = item.title
db_item.description = item.description
db.commit()
db.refresh(db_item)
return db_item
def delete_item(db: Session, item_id: int):
db_item = db.query(models.Item).filter(models.Item.id == item_id).first()
db.delete(db_item)
db.commit()
return db_item
4. Deployment
requirements.txt
requirements.txt
fastapi>=0.68.0,<0.69.0
pydantic>=1.8.0,<2.0.0
uvicorn>=0.15.0,<0.16.0
sqlalchemy>=1.3,<2.0
Dockerfile
Dockerfile
FROM python:3.9
WORKDIR /code
COPY ./requirements.txt /code/requirements.txt
# Install the package dependencies in the requirements file.
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
COPY ./app /code/app
# Set the command to run the uvicorn server.
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
Build image
docker build -t fastapi .
Run container
docker run -p 8000:8000 --restart unless-stopped --name fastapi -d fastapi