SQLAlchemy ORM Quick Start Guide
In this Quick Start, we will show you how to get started with SQLite Cloud by building a FastAPI backend that connects to and reads from a SQLite Cloud database using SQLAlchemy.
NOTE that FastAPI framework:
- does NOT require you to use a relational database or any database at all.
- CAN work with any ORM library (including SQLAlchemy) or database (including SQLite, which comes pre-installed in Python and is a database supported by SQLAlchemy).
- code is MINIMAL in the example below. Most of the code is standard SQLAlchemy and framework-agnostic.
- Set up a SQLite Cloud account
- If you haven’t already, sign up for a SQLite Cloud account and create a new project.
- In this guide, we will use the sample datasets that come pre-loaded with SQLite Cloud.
- Create a new Python project
- You should have the latest Python version (3) installed locally.
mkdir sqlalchemy-quickstart
cd sqlalchemy-quickstart
# open the project in VSCode / another editor
code .
python3 -m venv .venv
. .venv/bin/activate
- Install dependencies
- Run this command from your current directory:
pip install "fastapi[standard]" sqlalchemy sqlalchemy-sqlitecloud
- Do NOT remove the quotes around the FastAPI package.
sqlalchemy-sqlitecloudincludessqlitecloud, so no need to install the latter separately.
- App setup
- From your current directory, create a sub-directory
fastapi_sqlc_appwith an empty__init__.pyfile to indicate the new sub-directory is a package.- NOTE: We will create all remaining project files in this sub-directory.
mkdir fastapi_sqlc_app
cd fastapi_sqlc_app
touch __init__.py
- Create a new file
database.pyand copy in the following code.- In your SQLite Cloud account dashboard, click on
Show connection strings, copy the Connection String, and replace<your-connection-string>below. Modify your string to include the name of the DB we’ll query:sqlitecloud://{hostname}:8860/chinook.sqlite?apikey={apikey}.
- In your SQLite Cloud account dashboard, click on
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
engine = create_engine('<your-connection-string>')
SessionLocal = sessionmaker(bind=engine)
Base = declarative_base()
- Create a new file
models.pyand copy in the following code defining 2 SQLAlchemy ORM “models”, or classes, to interact with the DB.__tablename__is the name of a model’s corresponding DB table.- The
Albumclass’idattribute maps to theAlbumIdcolumn in thealbumstable. All other class attribute names match their corresponding table column names.
from .database import Base
from sqlalchemy import Column, ForeignKey, Integer, String
class Artist(Base):
__tablename__ = "artists"
ArtistId = Column(Integer, primary_key=True)
Name = Column(String)
class Album(Base):
__tablename__ = "albums"
id = Column("AlbumId", Integer, primary_key=True)
Title = Column(String)
ArtistId = Column(Integer, ForeignKey('artists.ArtistId'))
- Create a new file
schemas.pyand copy in the following code defining a Pydantic model, or “schema”, to validate the shape of the response data.
from pydantic import BaseModel
class AlbumResponse(BaseModel):
id: int
Title: str
ArtistName: str
- Create a new file
read.pyand copy in the following code creating a reusable utility function to read album data.
from . import models
from sqlalchemy.orm import Session
def get_albums(db: Session, skip: int = 0, num: int = 20):
return db.query(models.Album.id, models.Album.Title, models.Artist.Name.label('ArtistName')).join(models.Artist).offset(skip).limit(num).all()
- Create a new file
main.pyand copy in the following code.- The
get_dbfunction handles creating and closing a newSessionLocalinstance, or DB connection/ session, for every request. - A GET request to the
/albums/endpoint calls theread_albumsfunction, which returns a list of SQLAlchemyAlbummodels. Theresponse_modelensures only data declared in the Pydantic schema is returned to the client.- The
AlbumResponsePydantic model inschemas.pyhasArtistName, as opposed toArtistIddefined in theAlbumSQLAlchemy model inmodels.py. read_albumscalls theget_albumsfunction inread.py.get_albumsqueries theAlbumORM model/albumsDB table for the first 20 albums, and joins theArtistORM model/artistsDB table to retrieve theArtist.Name(re-labeledArtistName) expected by theAlbumResponsePydantic model.
- The
- The
from .database import SessionLocal
from . import read, schemas
from fastapi import FastAPI, Depends
from sqlalchemy.orm import Session
app = FastAPI()
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.get("/albums/", response_model=list[schemas.AlbumResponse])
def read_albums(skip: int = 0, num: int = 20, db: Session = Depends(get_db)):
albums = read.get_albums(db, skip=skip, num=num)
return albums
- Run your FastAPI app
- From your
sqlalchemy-quickstartdirectory, run the following command:
uvicorn fastapi_sqlc_app.main:app --reload
- Visit
http://127.0.0.1:8000/albums/to see your app data.
- Troubleshooting
- If you encounter the following error, restart your IDE and re-run your app.
AttributeError: module 'sqlitecloud.dbapi2' has no attribute 'sqlite_version_info'`
- References
And that’s it! You’ve successfully built a FastAPI app that uses SQLAlchemy ORM to read data from a SQLite Cloud database.