I'm always excited to take on new projects and collaborate with innovative minds.

Email

contact@niteshsynergy.com

Website

https://www.niteshsynergy.com/

Fast API

Welcome TO Fast API Blog from Nitesh Synergy

Module 1: Basics & Setup

 1. What is FastAPI?

FastAPI is a high-performance Python web framework used for building APIs, especially RESTful microservices.
It's built on:

  • Starlette (for the web parts like routing, middleware)
  • Pydantic (for data validation and parsing)

Think of it like Flask, but async-native, automatic docs via OpenAPI, and type-hint powered data validation.

 

2. Why FastAPI?

Compared to Flask or Django:

FeatureFlaskDjangoFastAPI
Async Support❌ (manual)⚠️ (partial)✅ Native
Type Hints⚠️✅ Full Support
Docs (Swagger)⚠️ (plugins)⚠️ (DRF needed)✅ Built-in
Speed🚶‍♂️ Slow🐢 Medium🚀 Fast

 

Use cases where FastAPI shines:

  • ML model deployment (TensorFlow, PyTorch, Transformers)
  • Async microservices (e.g., streaming APIs)
  • Low-latency systems (chat, notifications)

 

3. Installation and Environment Setup

A) Either do using any IDE 
 

screenshot-2025-07-20-193630.png


 

screenshot-2025-07-20-194142.png

 

or


B) Using Terminal

# 1. Create virtual environment
python -m venv venv
source venv/bin/activate   # On Windows: venv\Scripts\activate

# 2. Install FastAPI + uvicorn (ASGI server)
pip install fastapi uvicorn

# 3. Optional: for DevTools & extras
pip install python-dotenv[cli] httpx
 

 4. Running the First FastAPI App with Uvicorn

# main.py
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def root():
   return {"message": "Hello from FastAPI"}
 

Run it:

uvicorn main:app --reload

Now visit:

or 

Using IDE

image-249.png

 

5. FastAPI Directory Structure (Recommended for Production)

fastapi_app
├── main.py                # Entry point
├── app/
│   ├── __init__.py
│   ├── api/
│   │   ├── v1/
│   │   │   └── routes.py  # Routes
│   ├── core/
│   │   └── config.py      # Settings
│   ├── models/
│   │   └── user.py        # Pydantic Models
│   ├── services/
│   │   └── logic.py       # Business logic
│   └── db/
│       └── session.py     # DB sessions
├── requirements.txt
└── README.md
 

Done→

image-250.png

 

Code Explanation (main.py)

from fastapi import FastAPI

  • Imports the main FastAPI class.
  • Without this, you can't create your API object.

app = FastAPI()

  •  Creates the FastAPI app instance.
  • This is what uvicorn uses to serve requests.

@app.get("/")
async def root():
   return {"message": "Hello World"}
 

  •  @app.get("/"): Declares an endpoint for GET requests to /
  • async def root(): Async function that runs when / is hit
  • Returns JSON: {"message": "Hello World"}

 

@app.get("/hello/{name}")
async def say_hello(name: str):
   return {"message": f"Hello {name}"}
 

  •  /hello/{name}: Dynamic URL where {name} is a path parameter
  • If you call /hello/Rahul, FastAPI passes "Rahul" to the name parameter
  • JSON response with: "Hello Rahul"

curl http://localhost:8000/hello/Rahul
 

Project Structure from Screenshot

FastApi
├── .idea/
├── .venv/
├── main.py
├── FastApi.iml
├── test_main.http
├── External Libraries
├── Scratches and Consoles
 

🔹 .idea/

  • Created by PyCharm
  • Stores project-level configs like window layout, file history, etc.
  • Files like modules.xml, workspace.xml help PyCharm manage your environment

 You can ignore or .gitignore this folder in production code.

 

🔹 .venv/

  • Your virtual environment
  • Contains:
    • Scripts/: your Python binary and activate script
    • site-packages/: all your installed Python packages (FastAPI, Uvicorn, etc.)

 This is where your dependencies live.

 

🔹 main.py

  • Your main application file
  • FastAPI is run from here

You start the app using:

uvicorn main:app --reload
 

 

🔹 FastApi.iml

  • PyCharm module file.
  • Keeps track of settings like interpreter paths and project name.

 Not needed outside of PyCharm.

 

🔹 test_main.http

  • A PyCharm HTTP Client request file.
  • You can define and run test API requests from here instead of Postman.

 Example inside it:

 

### Get root endpoint
GET http://localhost:8000/

### Hello endpoint
GET http://localhost:8000/hello/Roman
 

 Then click the button above each request in the .http file to run it.

 

🔹 External Libraries

  • All installed dependencies visible via PyCharm
  • Comes from .venv/site-packages

 

🔹 Scratches and Consoles

  • Temporary files you write for testing
  • Not part of your core project

 

To change the port number when running your FastAPI app, you simply pass the --port argument to the uvicorn command.

Option 1: From Terminal

Default (port 8000):

uvicorn main:app --reload
 

Custom Port (e.g. 8080):

uvicorn main:app --reload --port 8080
 

Now your app will run at:

http://localhost:8080/
 

 

Option 2: From PyCharm (UI/Run Config)

If you’re running FastAPI using PyCharm’s green Run button (like in your screenshot):

Steps:

  1. Click Run > Edit Configurations…
  2. In the configuration for main, look for the Parameters field.
  3. Add this: main:app --reload --port 8080
     
  4. Click Apply → OK
  5. Run again — now it will start on port 8080

 

Change Host IP:

uvicorn main:app --reload --host 0.0.0.0 --port 8080
 

Make Sure Port Isn’t Blocked

If 8080 gives Connection Refused:

  • Check if another service is already using port 8080
  • Or try another port (e.g., 5000 or 9000)

You can check which port is used with:

netstat -a -n -o | findstr :8080
 

 

FastAPI port number configurable using a .env file and config.py

FastApi/
├── main.py
├── config.py          ← Load env vars
├── .env               ← Your config values
├── requirements.txt
└── ...
 

Create a .env file in the root:

HOST=127.0.0.1
PORT=8085
RELOAD=True
 

config.py File

from pydantic import BaseSettings

class Settings(BaseSettings):
   host: str = "127.0.0.1"
   port: int = 8000
   reload: bool = True

   class Config:
       env_file = ".env"

settings = Settings()
 

ain.py (use the app only)

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
   return {"message": "Hello World"}
 

No need to use settings in main.py. Just keep it clean.

 

Run Uvicorn Using the Config

python -c "import uvicorn; from config import settings; uvicorn.run('main:app', host=settings.host, port=settings.port, reload=settings.reload)"
 

Or add a script to your run.py:

 

from config import settings
import uvicorn

if __name__ == "__main__":
   uvicorn.run("main:app", host=settings.host, port=settings.port, reload=settings.reload)
 

python run.py
 

 

→ Rest check on github repo due to space concerns , using git repo as public repo.

 

complete guide to setting up and working with SQLAlchemy 2.0 (declarative model style) using IntelliJ IDEA, including:

  • DB setup (MySQL & MongoDB)
  • Configuration via settings.yml
  • Integration with Pydantic
  • Sync vs Async engines
  • Practical code structure

 

Prerequisites

Make sure you have:

  • IntelliJ IDEA (with Python plugin) or PyCharm
  • Python 3.9+
  • MySQL & MongoDB installed locally
  • pip configured

 

Required Packages

pip install sqlalchemy==2.0.*
pip install pymysql  # for MySQL
pip install pydantic
pip install pyyaml
pip install databases  # for async
pip install motor  # for MongoDB async
pip install pymongo  # for MongoDB sync
 

 

Project Structure:

your_project/

├── db/
│   ├── models.py
│   ├── database.py
│   └── settings.yml

├── schemas/
│   └── user.py

├── main.py
└── utils/
   └── config_loader.py
 

Step 1: settings.yml

 

mysql:
 user: root
 password: root
 host: localhost
 port: 3306
 database: test_db

mongodb:
 uri: "mongodb://localhost:27017"
 database: test_mongo
 

 

Step 2: Load YAML Config (config_loader.py)

import yaml
from pathlib import Path

def load_settings(file_path="db/settings.yml"):
   with open(Path(file_path), "r") as f:
       return yaml.safe_load(f)

settings = load_settings()
 

 

Step 3: MySQL + SQLAlchemy 2.0

db/database.py (for sync MySQL connection)

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, DeclarativeBase
from utils.config_loader import settings

class Base(DeclarativeBase):
   pass

MYSQL_URL = (
   f"mysql+pymysql://{settings['mysql']['user']}:"
   f"{settings['mysql']['password']}@"
   f"{settings['mysql']['host']}:"
   f"{settings['mysql']['port']}/"
   f"{settings['mysql']['database']}"
)

engine = create_engine(MYSQL_URL, echo=True)
SessionLocal = sessionmaker(bind=engine)
 

Step 4: Define Models (models.py)

from sqlalchemy import Column, Integer, String
from db.database import Base

class User(Base):
   __tablename__ = "users"

   id = Column(Integer, primary_key=True, index=True)
   name = Column(String(50))
   email = Column(String(100), unique=True, index=True)
 

Step 5: Create Tables

Step 6: Pydantic Integration (schemas/user.py)

from pydantic import BaseModel, EmailStr

class UserCreate(BaseModel):
   name: str
   email: EmailStr

class UserRead(UserCreate):
   id: int

   class Config:
       orm_mode = True
 

Step 7: Basic CRUD Example (main.py)

from db.database import SessionLocal
from db.models import User
from schemas.user import UserCreate

def create_user(user: UserCreate):
   db = SessionLocal()
   db_user = User(name=user.name, email=user.email)
   db.add(db_user)
   db.commit()
   db.refresh(db_user)
   db.close()
   return db_user

new_user = UserCreate(name="Nitesh", email="nitesh@test.com")
print(create_user(new_user))
 

Async Setup

db/database.py for async:

from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker
from sqlalchemy.orm import DeclarativeBase
from utils.config_loader import settings

class Base(DeclarativeBase):
   pass

ASYNC_MYSQL_URL = (
   f"mysql+aiomysql://{settings['mysql']['user']}:"
   f"{settings['mysql']['password']}@"
   f"{settings['mysql']['host']}:"
   f"{settings['mysql']['port']}/"
   f"{settings['mysql']['database']}"
)

async_engine = create_async_engine(ASYNC_MYSQL_URL, echo=True)
AsyncSessionLocal = async_sessionmaker(bind=async_engine, expire_on_commit=False)
 

 

🍃 MongoDB Setup

Sync MongoDB (pymongo)

from pymongo import MongoClient
from utils.config_loader import settings

mongo_client = MongoClient(settings["mongodb"]["uri"])
mongo_db = mongo_client[settings["mongodb"]["database"]]

users_collection = mongo_db["users"]

# Insert
users_collection.insert_one({"name": "Nitesh", "email": "me@a.in"})
 

Async MongoDB (motor)

import motor.motor_asyncio
from utils.config_loader import settings

mongo_client = motor.motor_asyncio.AsyncIOMotorClient(settings["mongodb"]["uri"])
mongo_db = mongo_client[settings["mongodb"]["database"]]

async def insert_user():
   await mongo_db["users"].insert_one({"name": "Async Nitesh", "email": "async@test.com"})
 

 

Sync vs Async SQLAlchemy

FeatureSync (Default SQLAlchemy)Async (via asyncio)
Enginecreate_enginecreate_async_engine
Sessionsessionmakerasync_sessionmaker
Performance (I/O bound)Lower (blocks event loop)Higher (non-blocking)
Use caseFast prototyping, simple APIsHigh-load APIs, async frameworks
Framework SupportWorks with Flask, FastAPIBest with FastAPI/Quart

 

IntelliJ IDEA Setup

  1. Install Python plugin (or use PyCharm).
  2. Create a Python project.
  3. Use virtualenv or poetry/pipenv.
  4. Create required directories (db/, schemas/, etc.).
  5. Right-click settings.ymlMark as Resource Root.
  6. Configure interpreter with required packages.
  7. Run main.py directly via IntelliJ run configuration.

 

screenshot-2025-07-29-192453.png

 

 

 

Next Steps After Clicking “Create”

  1. Activate Terminal inside IntelliJ.
  2. Run this in the terminal:

pip install sqlalchemy pymysql pydantic pyyaml pymongo motor databases
 

If you're using MySQL and MongoDB, this installs both sets of drivers.

  1. Structure Your Code

your_project/

├── db/
│   ├── models.py
│   ├── database.py
│   └── settings.yml

├── schemas/
│   └── user.py
├── main.py
├── utils/
│   └── config_loader.py
└── requirements.txt
 

You can generate requirements.txt using:

pip freeze > requirements.txt
 

How to Connect to Local MySQL

In settings.yml:

mysql:
 user: root
 password: your_password
 host: localhost
 port: 3306
 database: your_db
 

In code (for SQLAlchemy):

f"mysql+pymysql://{user}:{pwd}@{host}:{port}/{dbname}"
 

🍃 How to Connect to Local MongoDB

In settings.yml:

mongodb:
 uri: "mongodb://localhost:27017"
 database: test_mongo
 

In code (sync):

from pymongo import MongoClient

client = MongoClient(settings['mongodb']['uri'])
db = client[settings['mongodb']['database']]
 

In code (async):

import motor.motor_asyncio

client = motor.motor_asyncio.AsyncIOMotorClient(settings['mongodb']['uri'])
db = client[settings['mongodb']['database']]
 

 

Rest You can check code at repo layer.

Code Flow: From main.py → to DB

Let’s understand the full path:

main.py
└── calls
    ▼
services/user_service.py
└── uses
    ▼
db/models.py          (defines `User`)
db/database.py        (creates `SessionLocal`, engine, Base)
db/settings.yml       (contains DB config)
utils/config_loader.py (reads settings.yml)
 

 

So:

  1. main.py calls add_user(...) from user_service.

  2. user_service.py opens a DB session (SessionLocal()), creates a User from models.py, adds to DB.

  3. SessionLocal is created using engine from database.py, which uses DB config loaded from settings.yml.

 

 

How to Run It

Step 1: Make sure your main.py looks like this:

from services.user_service import add_user, get_all_users

if __name__ == "__main__":
   # Create new user
   user = add_user("rahuldev", "rahul@example.com", "Rahul Dev")
   print("New user added:", user)

   # Fetch all users
   users = get_all_users()
   for u in users:
       print(f"User: {u.username} | Email: {u.email}")
 

Step 2: Run inside terminal

In IntelliJ's terminal (bottom panel), type:

python main.py
 

This will:

  • Connect to your MySQL DB

  • Add a user (via add_user)

  • Print all users (via get_all_users)

 

3. Setup Checklist

To ensure everything works:

 settings.yml (inside db/):

mysql:
 user: root
 password: root
 host: localhost
 port: 3306
 database: champa
 

config_loader.py

import yaml
from pathlib import Path

def load_settings():
   with open(Path(__file__).parent.parent / "db" / "settings.yml", "r") as f:
       return yaml.safe_load(f)
 

database.py

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, declarative_base
from utils.config_loader import load_settings

settings = load_settings()
mysql = settings["mysql"]

DATABASE_URL = f"mysql+mysqlconnector://{mysql['user']}:{mysql['password']}@{mysql['host']}:{mysql['port']}/{mysql['database']}"

engine = create_engine(DATABASE_URL, echo=True)
SessionLocal = sessionmaker(bind=engine)
Base = declarative_base()
 

 

models.py

from sqlalchemy import Column, Integer, String, Text, TIMESTAMP, ForeignKey
from db.database import Base

class User(Base):
   __tablename__ = "users"
   user_id = Column(Integer, primary_key=True, autoincrement=True)
   username = Column(String(255))
   email = Column(String(255))
   full_name = Column(String(255))
   bio = Column(String(255))
   profile_image_url = Column(String(255))
   created_at = Column(TIMESTAMP)
 

 

In database.py, optionally run this once:

Base.metadata.create_all(bind=engine)
 

But since you already have tables in MySQL, you don’t need this — just map your models to existing tables.

 
 
 
 
 
 
12 min read
Jul 20, 2025
By Nitesh Synergy
Share

Leave a comment

Your email address will not be published. Required fields are marked *