Skip to content

Commit faf948e

Browse files
authored
add: FastAPI Tutorial
1 parent fdfb875 commit faf948e

File tree

3 files changed

+264
-0
lines changed

3 files changed

+264
-0
lines changed

Learn-FastAPI/FastAPI-CURD.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
from fastapi import FastAPI, HTTPException
2+
from pydantic import BaseModel
3+
from typing import List, Optional
4+
from uuid import UUID, uuid4
5+
6+
app = FastAPI()
7+
8+
# Define a Pydantic model for Task
9+
class Task(BaseModel):
10+
id: Optional[UUID] = None
11+
title: str
12+
description: Optional[str] = None
13+
completed: bool = False
14+
15+
# Initialize an empty list to store tasks
16+
tasks = []
17+
18+
# Create a new task
19+
@app.post("/tasks/", response_model=Task)
20+
def create_task(task: Task):
21+
task.id = uuid4() # Assign a UUID to the task
22+
tasks.append(task) # Add the task to the tasks list
23+
return task
24+
25+
# Retrieve all tasks
26+
@app.get("/tasks/", response_model=List[Task])
27+
def read_tasks():
28+
return tasks
29+
30+
# Retrieve a specific task by ID
31+
@app.get("/tasks/{task_id}", response_model=Task)
32+
def read_task(task_id: UUID):
33+
for task in tasks:
34+
if task.id == task_id:
35+
return task
36+
37+
# Raise HTTPException if task not found
38+
raise HTTPException(status_code=404, detail="Task not found")
39+
40+
# Update a specific task by ID
41+
@app.put("/tasks/{task_id}", response_model=Task)
42+
def update_task(task_id: UUID, task_update: Task):
43+
for idx, task in enumerate(tasks):
44+
if task.id == task_id:
45+
updated_task = task.copy(update=task_update.dict(exclude_unset=True))
46+
tasks[idx] = updated_task
47+
return updated_task
48+
49+
# Raise HTTPException if task not found
50+
raise HTTPException(status_code=404, detail="Task not found")
51+
52+
# Delete a specific task by ID
53+
@app.delete("/tasks/{task_id}", response_model=Task)
54+
def delete_task(task_id: UUID):
55+
for idx, task in enumerate(tasks):
56+
if task.id == task_id:
57+
return tasks.pop(idx)
58+
59+
# Raise HTTPException if task not found
60+
raise HTTPException(status_code=404, detail="Task not found")
61+
62+
# Run the FastAPI app
63+
if __name__ == "__main__":
64+
import uvicorn
65+
66+
uvicorn.run(app, host="0.0.0.0", port=8000)

Learn-FastAPI/FastAPI-Tutorial.py

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
from fastapi import Depends, FastAPI, HTTPException, status
2+
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
3+
from pydantic import BaseModel
4+
from datetime import datetime, timedelta
5+
from jose import JWTError, jwt
6+
from passlib.context import CryptContext
7+
8+
# Constants
9+
SECRET_KEY = ""
10+
ALGORITHM = "HS256"
11+
ACCESS_TOKEN_EXPIRE_MINUTES = 30
12+
13+
# Database simulation
14+
db = {
15+
"aman": {
16+
"username": "king04aman",
17+
"full_name": "Aman Kumar",
18+
"email": "[email protected]",
19+
"hashed_password": "$2b$12$HxWHkvMuL7WrZad6lcCfluNFj1/Zp63lvP5aUrKlSTYtoFzPXHOtu",
20+
"disabled": False
21+
}
22+
}
23+
24+
# Pydantic models
25+
class Token(BaseModel):
26+
access_token: str
27+
token_type: str
28+
29+
class TokenData(BaseModel):
30+
username: str or None = None
31+
32+
class User(BaseModel):
33+
username: str
34+
email: str or None = None
35+
full_name: str or None = None
36+
disabled: bool or None = None
37+
38+
class UserInDB(User):
39+
hashed_password: str
40+
41+
# Password hashing context
42+
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
43+
# OAuth2 password bearer
44+
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
45+
46+
# FastAPI instance
47+
app = FastAPI()
48+
49+
# Password helper functions
50+
def verify_password(plain_password, hashed_password):
51+
return pwd_context.verify(plain_password, hashed_password)
52+
53+
def get_password_hash(password):
54+
return pwd_context.hash(password)
55+
56+
# User authentication functions
57+
def get_user(db, username: str):
58+
if username in db:
59+
user_data = db[username]
60+
return UserInDB(**user_data)
61+
62+
def authenticate_user(db, username: str, password: str):
63+
user = get_user(db, username)
64+
if not user:
65+
return False
66+
if not verify_password(password, user.hashed_password):
67+
return False
68+
return user
69+
70+
# Token creation function
71+
def create_access_token(data: dict, expires_delta: timedelta or None = None):
72+
to_encode = data.copy()
73+
if expires_delta:
74+
expire = datetime.utcnow() + expires_delta
75+
else:
76+
expire = datetime.utcnow() + timedelta(minutes=15)
77+
to_encode.update({"exp": expire})
78+
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
79+
return encoded_jwt
80+
81+
# Dependency to get current user
82+
async def get_current_user(token: str = Depends(oauth2_scheme)):
83+
credential_exception = HTTPException(
84+
status_code=status.HTTP_401_UNAUTHORIZED,
85+
detail="Could not validate credentials",
86+
headers={"WWW-Authenticate": "Bearer"}
87+
)
88+
try:
89+
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
90+
username: str = payload.get("sub")
91+
if username is None:
92+
raise credential_exception
93+
token_data = TokenData(username=username)
94+
except JWTError:
95+
raise credential_exception
96+
97+
user = get_user(db, username=token_data.username)
98+
if user is None:
99+
raise credential_exception
100+
101+
return user
102+
103+
# Dependency to get current active user
104+
async def get_current_active_user(current_user: UserInDB = Depends(get_current_user)):
105+
if current_user.disabled:
106+
raise HTTPException(status_code=400, detail="Inactive user")
107+
return current_user
108+
109+
# Route to get access token
110+
@app.post("/token", response_model=Token)
111+
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
112+
user = authenticate_user(db, form_data.username, form_data.password)
113+
if not user:
114+
raise HTTPException(
115+
status_code=status.HTTP_401_UNAUTHORIZED,
116+
detail="Incorrect username or password",
117+
headers={"WWW-Authenticate": "Bearer"}
118+
)
119+
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
120+
access_token = create_access_token(
121+
data={"sub": user.username},
122+
expires_delta=access_token_expires
123+
)
124+
return {"access_token": access_token, "token_type": "bearer"}
125+
126+
# Route to get current user
127+
@app.get("/users/me/", response_model=User)
128+
async def read_users_me(current_user: User = Depends(get_current_active_user)):
129+
return current_user
130+
131+
# Route to get current user's items
132+
@app.get("/users/me/items")
133+
async def read_own_items(current_user: User = Depends(get_current_active_user)):
134+
return [{"item_id": 1, "owner": current_user}]

Learn-FastAPI/README.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# FastAPI CRUD and Authentication Example
2+
3+
This directory contains two FastAPI applications: one for basic CRUD operations (task management) and another for user authentication using JWT (JSON Web Tokens).
4+
5+
## Overview
6+
7+
1. **Task Management API (`fastapi-curd.py`)**:
8+
- Implements basic CRUD operations for managing tasks.
9+
- Tasks have attributes like `id`, `title`, `description`, and `completed`.
10+
11+
2. **User Authentication API (`fastapi-tutorial.py`)**:
12+
- Implements user registration, login, and token-based authentication.
13+
- Uses JWT for secure access and stores user information in a simulated database.
14+
15+
## Installation
16+
17+
To run the applications, ensure you have Python and FastAPI installed. You can install FastAPI and Uvicorn using pip:
18+
19+
```bash
20+
pip install fastapi uvicorn python-jose passlib[bcrypt]
21+
```
22+
23+
## Running the Applications
24+
25+
You can run each application separately.
26+
27+
### Task Management API
28+
29+
To run the task management API:
30+
31+
```bash
32+
python fastapi-curd.py
33+
```
34+
35+
The API will be available at `http://localhost:8000/tasks/`.
36+
37+
### User Authentication API
38+
39+
To run the user authentication API:
40+
41+
```bash
42+
python fastapi-tutorial.py
43+
```
44+
45+
The API will be available at `http://localhost:8000/token` for login and `http://localhost:8000/users/me/` for user information.
46+
47+
## API Endpoints
48+
49+
### Task Management API Endpoints
50+
51+
- **Create Task**: `POST /tasks/`
52+
- **Retrieve All Tasks**: `GET /tasks/`
53+
- **Retrieve Specific Task**: `GET /tasks/{task_id}`
54+
- **Update Task**: `PUT /tasks/{task_id}`
55+
- **Delete Task**: `DELETE /tasks/{task_id}`
56+
57+
### User Authentication API Endpoints
58+
59+
- **Token Generation**: `POST /token`
60+
- **Get Current User**: `GET /users/me/`
61+
- **Get Current User's Items**: `GET /users/me/items`
62+
63+
## Author
64+
- [king04aman](https://github.com/king04aman)

0 commit comments

Comments
 (0)