FastAPI Basics
A simple FastAPI application.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Create an app instance
app = FastAPI(root_path='/api/v1')
# Define path operation
@app.get('/') # Path operation decorator
async def root(): # Path operation function
return 'Hello, FastAPI!'
# Nested routes using APIRouter
users = APIRouter(prefix='/users', tags=['users'])
@users.get('/')
async def get_users(): ...
# Include routes of router (not router itself) to the app
app.include_router(users)
Setup
Install fastapi and all related dependencies, which includes uvicorn
, pydantic
, etc.
1
pip install "fastapi[all]"
Run
FastAPI is run by uvicorn
, an ASGI(Asynchronous Server Gateway Interface) web server implementation for python.
ASGI is a spiritual successor of WSGI(Web Server Gateway Interface) that supports async.
FastAPI will properly call both async and sync functions.
1
uvicorn main:app --host="0.0.0.0" --reload
Uvicorn converts the HTTP request, calls matching path operation, and again converts the return value into response.
OpenAPI
Automatically generates OAS based on annotations.
/docs
/redoc
/openapi.json
If you want to hide API docs, set openapi_url
as None on construction.
1
app = FastAPI(openapi_url=None)
Annotations
FastAPI automatically validates and converts(filters) the request/response with typing, but internally validation is done by pydantic.
All functions called by uvicorn performs pydantic validation, sucn as path operation, dependencies, but not manual function calls.
Pydantic
- Python library to perform data validation
- Inherits
BaseModel
BaseModel.__init__(self, **kwargs)
- No positional argument
- Initialize fields by keyword arguments
- Define fields => each field must be initialized by keyword arguments or falls to default or error
- (Required) Annotation: annotates type + metadata
- Used at type validation, but does not validate the type of default value
- Use Enum type to restrict available values
- There are not only basic types but special types like
EmailStr
, but might have to install additional dependencies - Use
Field
withAnnotated
to add metadata(validation, docs, etc.) - Pyantic raises
pydantic.ValidationError
when failed to validate, then handled by FastAPI (422 Unprocessable Entity)
- (Optional) Default: default value of the field
- (Required) Annotation: annotates type + metadata
DDD Structure Convention
fastapi-project
├── alembic/
├── src
│ ├── aws
│ │ ├── client.py # client model for external service communication
│ │ ├── schemas.py
│ │ ├── config.py
│ │ ├── constants.py
│ │ ├── exceptions.py
│ │ └── utils.py
│ └── posts
│ │ ├── router.py
│ │ ├── schemas.py # pydantic models
│ │ ├── models.py # db models
│ │ ├── dependencies.py
│ │ ├── config.py # local configs
│ │ ├── constants.py
│ │ ├── exceptions.py
│ │ ├── service.py
│ │ └── utils.py
│ ├── config.py # global configs
│ ├── models.py # global models
│ ├── exceptions.py # global exceptions
│ ├── pagination.py # global module e.g. pagination
│ ├── database.py # db connection related stuff
│ └── main.py
├── tests/
│ ├── auth
│ ├── aws
│ └── posts
├── templates/
│ └── index.html
├── requirements
│ ├── base.txt
│ ├── dev.txt
│ └── prod.txt
├── .env
├── .gitignore
├── logging.ini
└── alembic.ini
- Store all domain directories inside src folder
src/
- highest level of an app, contains common models, configs, and constants, etc.src/main.py
- root of the project, which inits the FastAPI app
- Each package has its own router, schemas, models, etc.
router.py
- is a core of each module with all the endpointsschemas.py
- for pydantic modelsmodels.py
- for db modelsservice.py
- module specific business logicdependencies.py
- router dependenciesconstants.py
- module specific constants and error codesconfig.py
- e.g. env varsutils.py
- non-business logic functions, e.g. response normalization, data enrichment, etc.exceptions.py
- module specific exceptions