Unlocking PostgreSQL: Connecting to FastAPI Server, Creating Tables On Ubuntu
Previously…
To deepen my understanding of PostgreSQL and Object-Relational Mappers (ORMs), I embarked on a project using PostgreSQL for manual database manipulation. This article builds on that journey by demonstrating how to connect a PostgreSQL database to a FastAPI server running on Ubuntu.
Prerequisites
This blog is a follow-up to my previous blog on how to set up PostgreSQL on Ubuntu. If you have not installed PostgreSQL on your Ubuntu you can refer to the article here before continuing. Once you’re done, you can continue with this blog:
Setting Up FastAPI
FastAPI is a lightweight and robust framework written in Python for developing APIs. It is well-known for its high performance and simplicity compared to other popular Python frameworks, such as Django. I particularly enjoy using FastAPI because it is easier to set up, and unlike Django, there is little to no abstraction involved. This allows me to have greater control over the configuration and behavior of my server.
Installation
To run FastAPI in Ubuntu is pretty easy, first open the Ubuntu desktop application you have on your system. Next, navigate to the project folder. Now you need to install python3 on Ubuntu.
sudo apt update
sudo apt install python3 python3-pip python3-venv
Now, that Python is installed successfully on your Ubuntu environment, the next will be creating the virtual environment.
python3 -m venv .venv --without-pip
This will create a .venv
folder in your project.
I will get into why we used the tag —without-pip
real soon.
Reason for the —without-pip
attribute
Ubuntu behaves weirdly with pip
. Usually when you install python3
, ensurepip
Should come preinstalled as a result. It is the package that helps manage and configure pip and its site-packages behaviors, but for some weird reason, when you try to create a virtual environment without the attribute —without-pip
, you will get this error:
theo@DESKTOP-Q1OABO1:/mnt/c/users/dell/desktop/projects/dummy$ python3 -m venv .venv
Error: Command '['/mnt/c/users/dell/desktop/projects/dummy/.venv/bin/python3.11', '-m', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1.
Installing ensurepip
separately does not work either. To solve this issue we need to install ensurepip
manually. To do this issue:
Create the virtual environment without pip:
python3 -m venv .venv --without-pip
Next, navigate to the
.venv
folder created and activate the virtual environment:cd .venv source bin/activate
Once that is completed, we can install
pip
manually by sending a request to thepip
set-up repository to download the configuration file:(.venv) theo@DESKTOP-Q1OABO1:/mnt/c/users/dell/desktop/projects/dummy/.venv$ wget https://bootstrap.pypa.io/get-pip.py --2024-12-31 13:09:13-- https://bootstrap.pypa.io/get-pip.py Resolving bootstrap.pypa.io (bootstrap.pypa.io)... 151.101.128.175, 2a04:4e42:400::175 Connecting to bootstrap.pypa.io (bootstrap.pypa.io)|151.101.128.175|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 2275758 (2.2M) [text/x-python] Saving to: ‘get-pip.py’ get-pip.py 100%[=================================================>] 2.17M 992KB/s in 2.2s 2024-12-31 13:09:17 (992 KB/s) - ‘get-pip.py’ saved [2275758/2275758]
Now that we have the
get-pip.py
file, we can now install pip manually:(.venv) theo@DESKTOP-Q1OABO1:/mnt/c/users/dell/desktop/projects/dummy/.venv$ python get-pip.py Collecting pip Using cached pip-24.3.1-py3-none-any.whl.metadata (3.7 kB) Collecting setuptools Using cached setuptools-75.6.0-py3-none-any.whl.metadata (6.7 kB) Collecting wheel Using cached wheel-0.45.1-py3-none-any.whl.metadata (2.3 kB) Using cached pip-24.3.1-py3-none-any.whl (1.8 MB) Using cached setuptools-75.6.0-py3-none-any.whl (1.2 MB) Using cached wheel-0.45.1-py3-none-any.whl (72 kB) Installing collected packages: wheel, setuptools, pip Successfully installed pip-24.3.1 setuptools-75.6.0 wheel-0.45.1
If you got through that with no problems, congratulations! You have pip installed now. Now let’s proceed with setting up the FastAPI server.
Now that we have that settled, we can finally install FastAPI with pip
:
pip install fastapi[standard] psycopg2-binary black isort asyncpg
Let’s get to know our tools:
fastapi[standard]
- FastAPI package withuvicorn
and other necessary packages installed by default.psycopg-binary
- PostgreSQL lightweight standalone database adapter that helps ease the connection to the PostgreSQL engine for Python.black
- Helps to format code during commits for Python.isort
- Formats Python code automatically as per configuration style.asyncpg
- Fast asynchronous database library for Python/asyncio and PostgreSQL
Once it’s all installed, next we create a file requirements.txt
and we move all our packages into the file:
pip freeze > requirements.txt
Now, that we have our environment ready, we can create a server.
Creating Server
In your project, create a file, main.py
or app.py
, you can name it whatever you wish. This is the file that initiates your FastAPI app, it can also be the file that loads everything that’s supposed to start up upon initiation. You can also write scripts here, or create endpoints as well. To create a FastAPI instance:
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
origins = [
"*",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get('/')
async def main():
return {
"status": 200,
"message": "App initialized"
}
It’s that easy. If we start the server, you will be able to access the endpoint via: 127.0.0.1:8000
:
uvicorn main:app --reload
Our server is live! Now let’s connect to our database.
Connecting to Database
To connect to the database, we need to write a script using the asyncpg
library:
import psycopg2
import asyncpg
import os
from dotenv import load_dotenv
from pathlib import Path
async def start_db():
conn = None
try:
conn = await asyncpg.connect(
host='127.0.0.1',
port=5432,
user='your_user',
password='your_password',
database='zappy_db' #Or the name of your database created from the previous article
)
print("Connecting to PostgreSQL")
return conn
except Exception as e:
print(f"Error: {e}")
finally:
if conn:
print("Connected")
Now we have to call this function in the main file so that when the application starts, our database is connected and active. To do this, create a function with the fastapi.app.on_event
decorator.
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from config.database import start_db
app = FastAPI()
origins = [
"*",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.on_event("startup")
async def on_startup():
await start_db()
Now when we reload our server again we get:
uvicorn main:app --reload
INFO: Will watch for changes in these directories: ['/mnt/c/users/dell/desktop/projects/dummy']
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [25253] using WatchFiles
INFO: Started server process [25257]
INFO: Waiting for application startup.
Connecting to PostgreSQL
Connected
INFO: Application startup complete.
Voila! We have successfully connected our FastAPI server to our PostgreSQL database. Now let’s create a table.
Creating Tables
To create a table, we need to write SQL scripts and run them in the Ubuntu terminal. To do that, create a file and save it with the .sql
extension to signify that it is an SQL script. Next, we write our scripts:
-- Create a FILES table
CREATE TABLE files (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NULL,
file_path VARCHAR(100) NOT NULL,
file_name VARCHAR(50) NOT NULL,
file_type file_type_enum,
file_status file_status_enum DEFAULT 'pending',
file_size BIGINT,
file_duration INTERVAL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NULL
);
Now that we have our scripts for creating the tables files
and transcription
, we can run a code to create these scripts and create the tables:
psql -U <your_user> -d zappy_db -f create.sql -h localhost
#Confirmation message
CREATE TABLE
And that’s it! We have successfully connected to and created a table in our PostgreSQL database on Ubuntu.
Some useful database operations
\dt
- Displays all tables/relations in the database.\d <table_name>
- Displays table with the table name if it exists on the database.\c <database_name
- Connects to the database with the database name.\l
- List all databases.\q
- Quits/exits from Postgres command-line interface.\conninfo
- Shows information about the current database connection.\dn
- List all schemas in the database.\di
- Lists all indexes in the database.\dv
- Lists all views in the database.
Conclusion
This article describes how to successfully connect a PostgreSQL database to a FastAPI server on Ubuntu and how to create a table successfully. I welcome your feedback in the comments section, as I am open to improving both myself and this article.
Thanks for reading!
References