ποΈ Enhancing the Database β Introducing the Users Table
In this lesson, we are upgrading our database architecture.
Up to this point, we only had a Todos table inside a database named:
todos.dbHowever, this naming is confusing because:
We have a database called
todosInside it, we also have a table called
todos
That lacks clarity and does not scale well.
So we are going to rename the database.
π Step 1 β Rename the Database
Inside database.py, where we configured SQLite, update the database name:
todos.db β todosapp.db
SQLALCHEMY_DATABASE_URL = "sqlite:///./todos.db"
SQLALCHEMY_DATABASE_URL = "sqlite:///./todosapp.db" 
This makes the database represent the entire application, not just one table.
Now our database will contain:
userstabletodostable
This is much cleaner and more scalable.
β οΈ Important Concept β SQLAlchemy Cannot Modify Tables
SQLAlchemy can:
β Create tables
β Can not Modify existing tables
If we want to enhance or alter existing tables properly in production, we use Alembic (database migrations).
We will cover Alembic later in this course.
ποΈ Step 2 β Update models.py
Before recreating the database, we must define our new structure.
We will:
Add a new
UserstableEnhance the
TodostableAdd a Foreign Key relationship
π€ Creating the Users Table
ποΈ models.py
from database import Base
from sqlalchemy import Column, Integer, String, Boolean
class Users(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True, index=True)
email = Column(String, unique=True)
username = Column(String, unique=True)
first_name = Column(String)
last_name = Column(String)
hashed_password = Column(String)
is_active = Column(Boolean, default=True)
role = Column(String)π Understanding Hashed Passwords (Critical Backend Concept)
We never store plain-text passwords.
Instead:
User enters a password
We hash it
We store only the hash
Hashing is one-way and cannot be reversed.
During login:
Hash the entered password
Compare it with the stored hash
If they match β login succeeds
β Developers canβt see passwords
β Leaked databases donβt expose passwords
β We compare hashes, not plain text
π Step 3 β Enhance the Todos Table
Now we update our existing Todos model.
ποΈ models.py
from sqlalchemy import Column, Integer, String, Boolean, ForeignKey
class Todos(Base):
__tablename__ = 'todos'
id = Column(Integer, primary_key=True, index=True)
title = Column(String)
description = Column(String)
priority = Column(Integer)
complete = Column(Boolean, default=False)
owner_id = Column(Integer, ForeignKey("users.id"))π What owner_id Means
owner_id = Column(Integer, ForeignKey("users.id"))This means:
Every todo must reference a user.
owner_idstores the primary key of the user.This creates a one-to-many relationship.
One user β Many todos
One todo β One user
Now when a user logs in:
We extract their
id.We fetch all todos where:
owner_id == user.id
That is how we securely isolate user data.
π Step 4 β Recreate the Database
Now:
Run the application
terminal
Delete the old database todos.db and todosapp.db
del todos.db
del todosapp.db
uvicorn main:app --reload
reload the browser
uvicorn main:app --reloaduvicorn main:app --reloadOn startup:
SQLAlchemy reads the models.
Creates
todosapp.db.Creates both
usersandtodostables.Applies the foreign key relationship.
β οΈ Important Reminder
Since we deleted the old database:
All previous todos are gone.
We will recreate data from scratch.
This is expected and correct.
We changed the schema.
ποΈ models.py
from database import Base
from sqlalchemy import Column, Integer, String, Boolean, ForeignKey
class Users(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True, index=True)
email = Column(String, unique=True)
username = Column(String, unique=True)
first_name = Column(String)
last_name = Column(String)
hashed_password = Column(String)
is_active = Column(Boolean, default=True)
role = Column(String)
class Todos(Base):
__tablename__ = "todos"
id = Column(Integer, primary_key=True, index=True)
title = Column(String, nullable=False)
description = Column(String)
priority = Column(Integer)
complete = Column(Boolean, default=False)
owner_id = Column(Integer, ForeignKey("users.id"))
No Changes in other files or folder structure