Back FASTAPI + SQLAlchemy + SQLite 25 Jun, 2026


from sqlalchemy import create_engine, Column, String, Integer
from sqlalchemy.orm import declarative_base, sessionmaker
from passlib.context import CryptContext

#password hashing context (bcrypt)
# Password hashing configuration

pwd_context= CryptContext(schemes= ["bcrypt"], deprecated= "auto")

# SQLite database URL

DATABASE_URL = "sqlite:///./users.db"

# Database engine
engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})

# Database session factory

SessionLocal= sessionmaker(bind= engine, autoflush=False, autocommit= False)

# Base class for models\
Base = declarative_base()

class User(Base):
    __tablename__= "users"

    id = Column(Integer, primary_key= True, index= True)
    username= Column(String, unique=True, index=True, nullable= False)
    hashed_password= Column(String, nullable= False)

# Create DB tables

Base.metadata.create_all(bind=engine)


This file is the foundation of your authentication system. It performs four main jobs:

  1. Configures password hashing.

  2. Connects to the database.

  3. Defines the database table.

  4. Creates the table if it doesn't exist.

Let's understand it conceptually, from the ground up.


Overall Architecture

                User Signs Up
                      │
                      ▼
            Hash Password (bcrypt)
                      │
                      ▼
              SQLAlchemy ORM
                      │
                      ▼
            SQLite Database Engine
                      │
                      ▼
                  users.db
                      │
                      ▼
                 users Table

Everything in this file is preparing this pipeline.


1. Import Required Libraries

from sqlalchemy import create_engine, Column, String, Integer
from sqlalchemy.orm import declarative_base, sessionmaker
from passlib.context import CryptContext

These libraries have different responsibilities.

SQLAlchemy

Think of SQLAlchemy as a translator.

Instead of writing SQL like:

SELECT * FROM users;

you write Python:

db.query(User)

SQLAlchemy converts Python into SQL.


Passlib

Passlib is responsible for password security.

Instead of storing:

mypassword123

it stores:

$2b$12$eLMF....

So even if someone steals your database, they cannot immediately read users' passwords.


2. Password Hashing Configuration

pwd_context = CryptContext(
    schemes=["bcrypt"],
    deprecated="auto"
)

Imagine you hire a security expert.

You tell him:

"Whenever someone gives me a password, lock it using bcrypt."

That's exactly what this configuration does.


Why bcrypt?

Because bcrypt is specifically designed for passwords.

Features:

  • Slow (hard for hackers to brute-force)

  • Salt is automatically added

  • One-way hashing

  • Industry standard


3. Database URL

DATABASE_URL = "sqlite:///./users.db"

This tells SQLAlchemy:

"Our database is stored in a file called users.db."

Breaking it apart:

sqlite:///

means

Use SQLite.

./

means

Current project folder.

users.db

means

Database filename.

If your project is:

project/
│
├── main.py
├── db_config.py

After running:

project/
│
├── main.py
├── db_config.py
├── users.db

4. Database Engine

engine = create_engine(
    DATABASE_URL,
    connect_args={"check_same_thread": False}
)

This creates the engine.

Think of the engine as the driver of a car.

FastAPI
    │
    ▼
SQLAlchemy
    │
    ▼
Engine
    │
    ▼
SQLite Database

Without the engine,

Python cannot communicate with SQLite.


Why check_same_thread=False?

SQLite normally allows only one thread to use the database connection.

FastAPI serves many users simultaneously.

So we allow SQLAlchemy to manage connections across requests safely.


5. Session Factory

SessionLocal = sessionmaker(
    bind=engine,
    autoflush=False,
    autocommit=False
)

This is one of the most important concepts.

Imagine the database is a bank.

Every customer gets a token to interact with the bank.

That token is called a Session.

Database

      ▲
      │
Session

Whenever you need the database:

db = SessionLocal()

you receive a brand-new session.


Why not use the engine directly?

The engine is like the bank building.

The session is like your bank counter.

Each user/request gets their own counter.


6. Base Class

Base = declarative_base()

This creates the parent class for all database models.

Think of it as saying:

"Every class that inherits from Base becomes a database table."

Without Base:

class User:

is just a normal Python class.

With Base:

class User(Base):

SQLAlchemy knows:

This represents a database table.


7. User Model

class User(Base):

This is called an ORM Model.

It represents one table inside the database.


Table Name

__tablename__ = "users"

Database:

users

table.


8. Columns

Primary Key

id = Column(
    Integer,
    primary_key=True,
    index=True
)

Database:

id
1
2
3

Every user gets a unique ID.


Username

username = Column(
    String,
    unique=True,
    index=True,
    nullable=False
)

Meaning:

String

Text.


unique=True

No duplicates.

Allowed:

abhishek
rahul

Not allowed:

abhishek
abhishek

index=True

Creates an index.

Imagine a book.

Without index:

Page 1
Page 2
Page 3
...
Page 500

Need to search every page.

With index:

A
Abhishek → Page 120

Searching becomes much faster.


nullable=False

Cannot be empty.

Not allowed:

username = NULL

9. Password Column

hashed_password = Column(
    String,
    nullable=False
)

Notice:

Not

password

Instead:

hashed_password

This reminds everyone:

We never store plain passwords.


10. Create Tables

Base.metadata.create_all(bind=engine)

This checks:

Does users table exist?

If yes:

Do nothing.

If no:

Create it.

Equivalent SQL:

CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    username VARCHAR UNIQUE,
    hashed_password VARCHAR
);

What Gets Stored?

Suppose user signs up.

Username

abhishek

Password

mypassword123

Password becomes

$2b$12$Kd9r....

Database:

idusernamehashed_password
1abhishek$2b$12$Kd9r....

Notice:

The original password never enters the database.


Complete Picture

User
 │
 │ Signup
 ▼
Enter Username + Password
 │
 ▼
hash_password()
 │
 ▼
bcrypt Hash
 │
 ▼
User Object
 │
 ▼
SQLAlchemy ORM
 │
 ▼
Engine
 │
 ▼
users.db
 │
 ▼
users Table
 │
 ├── id
 ├── username
 └── hashed_password

Significance of each component

ComponentPurpose
CryptContextDefines how passwords are securely hashed and verified.
DATABASE_URLSpecifies where the database is located.
engineOpens and manages the connection between Python and the database.
SessionLocalCreates an isolated database session for each request.
BaseMarks classes as SQLAlchemy ORM models.
UserDefines the structure of the users table.
ColumnDefines individual fields (columns) of the table.
create_all()Automatically creates the table if it doesn't already exist.

Once you understand this file, you've grasped the core of how FastAPI + SQLAlchemy models, sessions, and database connections work together. The next layer is learning how CRUD operations (Create, Read, Update, Delete) use SessionLocal and the User model to interact with users.db.

Rate This Note
Login to Rate This Note