Configuring Python FastAPI with SqlAlchemy and Alembic
FastAPI is a promising framework to build high performance web applications that needs Async support. It also brings in best practices for a high quality production application.
Let’s take a quick view of few building blocks that we will use in this article.
FastAPI
FastAPI is build using two important framework for well defined responsibilities :
To run FastAPI based application we will need an ASGI server such as Uvicorn or Hypercorn.
Starlette
Starlette is a lightweight ASGI framework/toolkit, which is ideal for building high performance asyncio services.
Pydantic
pydantic enforces type hints at runtime, and provides user friendly errors when data is invalid. We can define how data should be in pure python and validate it easily with pydantic.
ASGI specification
ASGI (Asynchronous Server Gateway Interface) is a spiritual successor to WSGI, intended to provide a standard interface between async-capable Python web servers, frameworks, and applications.
Uvicorn server
Uvicorn is a lightning-fast ASGI server, built on uvloop and httptools.
Alembic
Alembic is a lightweight database migration tool for usage with the SQLAlchemy Database Toolkit for Python
Getting started
Let’s install only libraries that we will use:
# Use python 3.6+
pipenv install fastapi uvicorn sqlalchemy alembic
Uvicorn installation error
On doing the above installation of uvicorn, in my case resulted in an error. One of the dependency of uvicorn → unicorn errored out saying :
ERROR: Cannot use 'python', Python 2.4 or later is required.", ' Note that Python 3 or later is not yet supported.'
But uvicorn seems functional though installation had an error. I didn’t fully understand the reason., But it is not blocking our project.
Environment based configuration
pipenv install python-dotenv
Directory structure (end result )
.
├── Dockerfile
├── Pipfile
├── Pipfile.lock
├── README.md
├── alembic.ini
├── app
│ ├── __init__.py
│ ├── config
│ │ ├── __init__.py
│ │ ├── prod.env
│ │ └── qa.env
│ ├── database.py
│ ├── main.py
│ ├── models
│ │ ├── __init__.py
│ └── schemas
├── migration
│ ├── README
│ ├── env.py
│ ├── script.py.mako
│ └── versions
│ └── 66d8a54cd297_initial_tables.py
├── start.sh
Create a directory config
and have environment configurations there.
#__init__.py
from pydantic import BaseSettingsclass Settings(BaseSettings):
# default conf goes here
app_name: str = "Awesome API"
admin_email: str
items_per_user: int = 50 class Config:
env_file = ".env"
Alembic
# Initialize alembic database migration flow
$ alembic init db-migration
- Update alembic’s env.py with environment based
db_url
with customget_url
method as shown below - update
run_migration_offline
as shown below - update
run_migration_online
as shown below - update
target_metadata
This is needed forautogeneration
of migration scripts
Alembic autogeneration of migration scripts
- For autogeneration to work, alembic should be able to detect all models that we have in the application.
- Below
__init__.py
will help to automatically add all models that exists into__all__
so that we can doimport *
as shown inenv.py
We make use of autogeneration of schema changes. With this, we can make changes to database models and run autogenerate — this will generate the changes as script.
# This will scan the models and generate upgrade & downgrade scripts
alembic revision --autogenerate -m “Initial tables”
Running db migration
Detailed information on alembic commands can be found here.
Here is a quick reference:
# following command will run all migration script and bring it to latest version
alembic upgrade head
# If we like to incrementally upgrade and check for some errors
alembic upgrade +1
# To undo last migration
alembic downgrade -1
# To get more information
alembic current
alembic history - verbose
Summary
- SQLAlchemy Model creation is well documented in fastapi documentation. So this article is not diving into those details.
- Configuring alembic with fastapi and getting autogeneration working is little tricky.
- Above setup with env based config should come handy, if you are trying to setup one.
Useful links
- Full stack, modern web application generator. Using FastAPI, PostgreSQL as database, Docker, automatic HTTPS and more
- Async — Await in FastAPI with good explanation on concurrency vs parallelism
- Alembic’s documentation on getting started
- API documentation metadata configuration
- Application configuration management
- FastAPI document has few suggestions on folder structures.