Skip to content

Commit 59e7521

Browse files
committed
rewrite application with async operetion
1 parent 7445ae6 commit 59e7521

7 files changed

Lines changed: 116 additions & 98 deletions

File tree

app.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,30 @@
11
from routes.posts import PostRouter
22
from routes.users import UserRouter
3-
from fastapi import FastAPI, Depends
4-
from auth.jwt_bearer import JWTBearer
5-
from fastapi import Request
6-
from middleware.middleware import CollectMiddleware
3+
from fastapi import FastAPI
4+
from database.database import engine
75

86

9-
app = FastAPI()
7+
app = FastAPI(description="Template for building FastAPI applications with PostgreSQL", contact={"email": "samanidarix@gmail.com"})
108

119

12-
app.add_middleware(CollectMiddleware, redis_host="localhost", redis_port="6379")
1310

1411

15-
token_listener = JWTBearer()
12+
@app.on_event("startup")
13+
async def startup():
14+
await engine.connect()
15+
16+
@app.on_event("shutdown")
17+
async def shutdown():
18+
await engine.dispose()
19+
20+
1621

1722

1823
@app.get("/", tags=["Root"])
1924
async def read_root():
2025
return {"message": "Welcome to this fantastic app."}
2126

2227

28+
2329
app.include_router(UserRouter, tags=["USERS"], prefix="/users")
24-
app.include_router(PostRouter, tags=["Posts"], prefix="/posts", dependencies=[Depends(token_listener)],)
30+
app.include_router(PostRouter, tags=["Posts"], prefix="/posts",)

auth/deps.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,31 @@
11
from fastapi import Depends, status
2-
from sqlalchemy.orm import Session
3-
from database.database import SessionLocal
2+
from sqlalchemy.ext.asyncio import AsyncSession
3+
from database.database import AsyncSessionLocal
44
from auth.jwt_handler import decode_jwt
55
from fastapi.security import OAuth2PasswordBearer
66
from fastapi.exceptions import HTTPException
77
from database.dao.dao_users import DaoUser
88

9-
def get_db():
10-
db = SessionLocal()
11-
try:
12-
yield db
13-
finally:
14-
db.close()
9+
async def get_db():
10+
async with AsyncSessionLocal() as session:
11+
yield session
1512

1613
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/users/token")
1714

18-
def get_current_user(db: Session = Depends(get_db), token :str = Depends(oauth2_scheme)):
15+
async def get_current_user(db: AsyncSession = Depends(get_db), token :str = Depends(oauth2_scheme)):
1916

2017
users_exits = decode_jwt(token=token)
2118

22-
print(f"user exists : {users_exits}")
23-
2419
if not users_exits:
2520
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Could not validate credentials")
2621

2722
daoUser = DaoUser(db=db)
23+
24+
user = await daoUser.get_user_by_email(email=users_exits["email"])
25+
26+
if not user:
27+
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Could not validate credentials")
2828

29-
return daoUser.get_user_by_email(email=users_exits["email"])
29+
return user
3030

3131

database/dao/dao_posts.py

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,45 @@
1-
from sqlalchemy.orm import Session
1+
from sqlalchemy.future import select
22
from models.posts import Post
33
from schemas.posts import PostCreate
4-
from database.database import SessionLocal
4+
from sqlalchemy.ext.asyncio import AsyncSession
55

66

77
class DaoPost():
88

9-
db : Session
9+
db : AsyncSession
1010

1111

12-
def __init__(self, db: Session):
12+
def __init__(self, db: AsyncSession):
1313
self.db = db
1414

1515

16-
def get_post_user(self, user_id: int):
17-
posts_user = self.db.query(Post).filter(Post.user_id==user_id).all()
18-
return posts_user
19-
20-
def get_post_by_id(self, post_id: int):
21-
post = self.db.query(Post).filter(Post.id==post_id).first()
16+
async def get_post_user(self, user_id: int):
17+
result = await self.db.execute(select(Post).where(Post.user_id == user_id))
18+
posts = result.scalars()
19+
return posts
20+
21+
async def get_post_by_id(self, post_id: int):
22+
result = await self.db.execute(select(Post).where(Post.id == post_id))
23+
post = result.scalar_one_or_none()
2224
return post
2325

24-
def get_post_by_user_id(self, user_id:int):
25-
post = self.db.query(Post).filter(Post.user_id==user_id).first()
26-
return post
26+
async def get_post_by_user_id(self, user_id:int):
27+
28+
result = await self.db.execute(select(Post).filter(Post.user_id == user_id))
29+
posts = result.scalars()
30+
return posts
2731

2832

2933

30-
def create_post(self, post_create:PostCreate, user_id: int):
34+
async def create_post(self, post_create:PostCreate, user_id: int):
3135
post = Post(title=post_create.title, content=post_create.content, user_id=user_id)
3236
self.db.add(post)
33-
self.db.commit()
34-
self.db.refresh(post)
37+
await self.db.commit()
38+
await self.db.refresh(post)
3539

3640
return post
3741

38-
def delete_post(self, post: Post):
42+
async def delete_post(self, post: Post):
3943

40-
self.db.delete(post)
41-
self.db.commit()
44+
await self.db.delete(post)
45+
await self.db.commit()

database/dao/dao_users.py

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
from sqlalchemy.orm import Session
1+
from sqlalchemy.future import select
2+
from sqlalchemy.ext.asyncio import AsyncSession
23
from models.users import User
34
from pydantic import EmailStr
45
from passlib.context import CryptContext
56
from schemas.users import UserCreate
67
from models.users import User
7-
from database.database import SessionLocal
8+
import asyncio
89

910
hash_helper = CryptContext(schemes=["bcrypt"])
1011

@@ -13,40 +14,45 @@
1314

1415
class DaoUser():
1516

16-
db : Session
17+
db : AsyncSession
1718

18-
def __init__(self, db: Session) -> None:
19+
def __init__(self, db: AsyncSession) -> None:
1920
self.db = db
2021

21-
def get_users(self):
22+
async def get_users(self):
2223
users = self.db.query(User).all()
2324
return users
2425

2526

26-
def get_user_by_email(self, email: str):
27-
user = self.db.query(User).filter(User.email==email).first()
27+
async def get_user_by_email(self, email: str):
28+
29+
result = await self.db.execute(select(User).where(User.email == email))
30+
user = result.scalar_one_or_none()
2831
return user
2932

30-
def get_user_by_id(self, user_id: int):
31-
user = self.db.query(User).filter(User.id==user_id).first()
33+
async def get_user_by_id(self, user_id: int):
34+
result = await self.db.execute(select(User).where(User.id == user_id))
35+
user = result.scalar_one_or_none()
3236
return user
3337

3438

35-
def create_new_user(self, user: UserCreate):
39+
async def create_new_user(self, user: UserCreate):
3640
user_db = User(email=user.email, fullname=user.fullname, password = hash_helper.encrypt(user.password))
3741
self.db.add(user_db)
38-
self.db.commit()
39-
self.db.refresh(user_db)
42+
await self.db.commit()
43+
await self.db.refresh(user_db)
4044
return user_db
4145

42-
def get_users(self, skip: int = 0, limit: int = 100):
43-
return self.db.query(User).offset(skip).limit(limit).all()
46+
async def get_users(self, skip: int = 0, limit: int = 100):
47+
result = await self.db.execute(select(User).offset(skip).limit(limit))
48+
users = result.scalars()
49+
return users
4450

4551

46-
def delete_user(self, user):
52+
async def delete_user(self, user):
4753

48-
self.db.delete(user)
49-
self.db.commit()
54+
await self.db.delete(user)
55+
await self.db.commit()
5056

5157

5258

database/database.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import dotenv
22
from sqlalchemy import create_engine
33
from sqlalchemy.ext.declarative import declarative_base
4-
from sqlalchemy.orm import sessionmaker
4+
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker
5+
from typing import Callable
56
from config.config import settings
67
import os
78

@@ -14,14 +15,17 @@ def get_url():
1415
server = os.getenv("POSTGRES_SERVER", "localhost")
1516
db = os.getenv("POSTGRES_DB", "darix")
1617
port = os.getenv("POSTGRES_PORT", 5432)
17-
return f"postgresql://{user}:{password}@{server}:{port}/{db}"
18+
return f"postgresql+asyncpg://{user}:{password}@{server}:{port}/{db}"
1819

1920

2021
SQLALCHEMY_DATABASE_URL = get_url()
2122

2223
print(f"SQLALCHEMY_DATABASE_URL : {SQLALCHEMY_DATABASE_URL}")
23-
engine = create_engine(SQLALCHEMY_DATABASE_URL)
24-
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
24+
25+
engine = create_async_engine(SQLALCHEMY_DATABASE_URL)
26+
27+
28+
AsyncSessionLocal: Callable[[], AsyncSession] = async_sessionmaker(autocommit=False, autoflush=False, bind=engine, class_=AsyncSession)
2529

2630
Base = declarative_base()
2731

routes/posts.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,39 @@
1-
from fastapi import APIRouter, Depends
2-
from sqlalchemy.orm import Session
1+
from fastapi import APIRouter, Depends, status
2+
from sqlalchemy.ext.asyncio import AsyncSession
33
from auth.deps import get_db, get_current_user
44
from schemas.posts import PostCreate
55
from models.users import User
66
from fastapi import HTTPException
77
from database.dao.dao_posts import DaoPost
8+
from database.dao.dao_users import DaoUser
89
from schemas.posts import PostResponseModel
910

1011
PostRouter = APIRouter()
1112

1213

1314
@PostRouter.post("", response_model=PostResponseModel)
14-
def create_new_post(post_create: PostCreate, db: Session = Depends(get_db), user_create: User = Depends(get_current_user)):
15-
print(f"user : {user_create}")
15+
async def create_new_post(post_create: PostCreate, db: AsyncSession = Depends(get_db), user: User = Depends(get_current_user)):
16+
1617
daoPost = DaoPost(db=db)
17-
post = daoPost.create_post(post_create=post_create, user_id=user_create.id)
18+
daoUser = DaoUser(db=db)
19+
post = await daoPost.create_post(post_create=post_create, user_id=user.id)
1820

1921
if not post:
20-
2122
raise HTTPException(status_code=403, detail="unable to create post")
2223

2324
return post
2425

2526

2627
@PostRouter.delete("/{id_post}")
27-
def delete_posts(id_post:int , db: Session = Depends(get_db), user_create: User = Depends(get_current_user)):
28+
async def delete_posts(id_post:int, db: AsyncSession = Depends(get_db), user: User = Depends(get_current_user)):
2829
daoPost = DaoPost(db=db)
2930

30-
post = daoPost.get_post_by_id(post_id=id_post)
31+
post_exist = await daoPost.get_post_by_id(post_id=id_post)
3132

32-
if not post:
33+
if not post_exist:
3334

34-
raise HTTPException(status_code=403, detail="Post don't exists")
35+
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Post don't exists")
3536

36-
daoPost.delete_post(post=post)
37+
await daoPost.delete_post(post=post_exist)
3738

38-
return {"detail": f"Post with id {post.id} successfully deleted"}
39+
return HTTPException(status_code=status.HTTP_200_OK, detail=f"Post with id: {post_exist.id} successfully deleted")

0 commit comments

Comments
 (0)