Skip to content

Commit b1a6267

Browse files
author
SuRu
committed
added exception handling
1 parent 40d787d commit b1a6267

File tree

9 files changed

+90
-52
lines changed

9 files changed

+90
-52
lines changed

app/__init__.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from fastapi import FastAPI, Request, status
2+
from fastapi.responses import JSONResponse
3+
4+
from app.exceptions import EntityNotFoundException
5+
from app.routers import branch, student
6+
7+
app = FastAPI(
8+
title='Students API',
9+
description='Simple python students API',
10+
version='1.0.0',
11+
contact={
12+
'name': 'SuRu',
13+
'url': 'https://github.com/suru33/students-api-python',
14+
'email': '33urus@gmail.com'
15+
},
16+
license_info={
17+
'name': 'GNU General Public License v2.0',
18+
'url': 'https://github.com/suru33/students-api-python/blob/master/LICENSE'
19+
}
20+
)
21+
22+
app.include_router(branch.router)
23+
app.include_router(student.router)
24+
25+
26+
@app.exception_handler(EntityNotFoundException)
27+
async def entity_not_found_exception_handler(request: Request, ex: EntityNotFoundException):
28+
return JSONResponse(
29+
status_code=status.HTTP_404_NOT_FOUND,
30+
content={
31+
"path": request.url.path,
32+
"message": f"{ex.name}: {ex.value} does not exist"
33+
},
34+
)

app/exceptions.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from uuid import UUID
2+
3+
4+
class EntityNotFoundException(Exception):
5+
def __init__(self, name: str, value: UUID):
6+
self.name = name
7+
self.value = value

app/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class Student(Base):
1919

2020
id = Column(name='s_id', type_=UUID(as_uuid=True), primary_key=True, index=True)
2121
name = Column(name='s_name', type_=String, nullable=False)
22-
branch = Column(name='s_branch', type_=UUID, nullable=False)
22+
branch = Column(name='s_branch', type_=UUID(as_uuid=True), nullable=False)
2323
year = Column(name='s_year', type_=Integer, nullable=False)
2424
dob = Column(name='s_dob', type_=DATE, nullable=False)
2525
email = Column(name='s_email', type_=String, nullable=False)

app/repositories/branch_repository.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from datetime import datetime
2-
from uuid import uuid4
2+
from uuid import UUID, uuid4
33

44
from sqlalchemy.orm import Session
55

6+
from app.exceptions import EntityNotFoundException
67
from app.models import Branch
78
from app.schemas import BranchRequest
89

@@ -21,8 +22,12 @@ def create_branch(db: Session, request: BranchRequest):
2122
return branch
2223

2324

24-
def get_branch_by_id(db: Session, branch_id: str):
25-
return db.query(Branch).filter(Branch.id == branch_id).first()
25+
def get_branch_by_id(db: Session, branch_id: UUID):
26+
branch = db.query(Branch).filter(Branch.id == branch_id).first()
27+
if branch:
28+
return branch
29+
30+
raise EntityNotFoundException('branch', branch_id)
2631

2732

2833
def get_all_branches(db: Session):

app/repositories/student_repository.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
from datetime import datetime
2-
from uuid import uuid4
2+
from uuid import UUID, uuid4
33

44
from sqlalchemy.orm import Session
55

6+
from app.exceptions import EntityNotFoundException
67
from app.models import Student
8+
from app.repositories import branch_repository
79
from app.schemas import StudentRequest
810

911

10-
def create_student(db: Session, request: StudentRequest):
12+
def create_student(db: Session, branch_id: UUID, request: StudentRequest):
13+
branch = branch_repository.get_branch_by_id(db, branch_id)
14+
1115
student = Student(
1216
id=uuid4(),
1317
name=request.name,
14-
branch=request.branch,
18+
branch=branch.id,
1519
year=request.year,
1620
dob=request.dob,
1721
email=request.email,
@@ -25,8 +29,12 @@ def create_student(db: Session, request: StudentRequest):
2529
return student
2630

2731

28-
def get_student_by_id(db: Session, student_id: str):
29-
return db.query(Student).filter(Student.id == student_id).first()
32+
def get_student_by_id(db: Session, student_id: UUID):
33+
student = db.query(Student).filter(Student.id == student_id).first()
34+
if student:
35+
return student
36+
37+
raise EntityNotFoundException('student', student_id)
3038

3139

3240
def get_all_students(db: Session):

app/routers/branch.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
from typing import List
2+
from uuid import UUID
23

3-
from fastapi import APIRouter, Depends, HTTPException
4+
from fastapi import APIRouter, Depends, HTTPException, status
45
from sqlalchemy.orm import Session
56

67
from app.dependencies import get_db
7-
from app.repositories import branch_repository as repository
8-
from app.schemas import BranchRequest, BranchResponse
8+
from app.repositories import branch_repository as repository, student_repository
9+
from app.schemas import BranchRequest, BranchResponse, StudentRequest, StudentResponse
910

1011
router = APIRouter(prefix="/branch", tags=["branch"])
1112

@@ -16,13 +17,18 @@ async def get_all_branches(db: Session = Depends(get_db)):
1617

1718

1819
@router.get("/{branch_id}", response_model=BranchResponse)
19-
async def get_branch_by_id(branch_id, db: Session = Depends(get_db)):
20+
async def get_branch_by_id(branch_id: UUID, db: Session = Depends(get_db)):
2021
branch = repository.get_branch_by_id(db, branch_id)
2122
if branch is None:
2223
raise HTTPException(status_code=404, detail="Branch not found")
2324
return branch
2425

2526

26-
@router.post("/", response_model=BranchResponse)
27+
@router.post("/", response_model=BranchResponse, status_code=status.HTTP_201_CREATED)
2728
async def create_branch(request: BranchRequest, db: Session = Depends(get_db)):
2829
return repository.create_branch(db, request)
30+
31+
32+
@router.post("/{branch_id}/student", response_model=StudentResponse, status_code=status.HTTP_201_CREATED)
33+
async def create_student(request: StudentRequest, branch_id: UUID, db: Session = Depends(get_db)):
34+
return student_repository.create_student(db, branch_id, request)

app/routers/student.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
from typing import List
2+
from uuid import UUID
23

34
from fastapi import APIRouter, Depends, HTTPException
45
from sqlalchemy.orm import Session
56

67
from app.dependencies import get_db
78
from app.repositories import student_repository as repository
8-
from app.schemas import StudentRequest, StudentResponse
9+
from app.schemas import StudentResponse
910

1011
router = APIRouter(prefix="/student", tags=["student"])
1112

@@ -16,13 +17,11 @@ async def get_all_students(db: Session = Depends(get_db)):
1617

1718

1819
@router.get("/{student_id}", response_model=StudentResponse)
19-
async def get_student_by_id(student_id, db: Session = Depends(get_db)):
20+
async def get_student_by_id(student_id: UUID, db: Session = Depends(get_db)):
2021
student = repository.get_student_by_id(db, student_id)
2122
if student is None:
2223
raise HTTPException(status_code=404, detail="Student not found")
2324
return student
2425

2526

26-
@router.post("/", response_model=StudentResponse)
27-
async def create_student(request: StudentRequest, db: Session = Depends(get_db)):
28-
return repository.create_student(db, request)
27+

app/schemas.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
from datetime import date, datetime
22
from uuid import UUID
33

4-
from pydantic import BaseModel
4+
from pydantic import BaseModel, EmailStr, conint, constr
55

66

77
class BranchRequest(BaseModel):
8-
short_name: str
9-
name: str
8+
short_name: constr(strict=True, min_length=3, max_length=10)
9+
name: constr(strict=True, min_length=3, max_length=100)
1010

1111

1212
class BranchResponse(BaseModel):
@@ -21,21 +21,20 @@ class Config:
2121

2222

2323
class StudentRequest(BaseModel):
24-
name: str
25-
branch: str
26-
year: int
27-
dob: str
28-
email: str
29-
phone: str
24+
name: constr(strict=True, min_length=3, max_length=100)
25+
year: conint(strict=True, ge=1, le=4)
26+
dob: date
27+
email: EmailStr
28+
phone: constr(strict=True, min_length=5, max_length=20)
3029

3130

3231
class StudentResponse(BaseModel):
3332
id: UUID
3433
name: str
35-
branch: str
36-
year: int
34+
branch: UUID
35+
year: conint(strict=True, ge=1, le=4)
3736
dob: date
38-
email: str
37+
email: EmailStr
3938
phone: str
4039
created_at: datetime
4140
updated_at: datetime

main.py

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,4 @@
1-
from fastapi import FastAPI
2-
3-
from app.routers import branch, student
4-
5-
app = FastAPI(
6-
title='Students API',
7-
description='Simple python students API',
8-
version='1.0.0',
9-
contact={
10-
'name': 'SuRu',
11-
'url': 'https://github.com/suru33/students-api-python',
12-
'email': '33urus@gmail.com'
13-
},
14-
license_info={
15-
'name': 'GNU General Public License v2.0',
16-
'url': 'https://github.com/suru33/students-api-python/blob/master/LICENSE'
17-
}
18-
)
19-
20-
app.include_router(branch.router)
21-
app.include_router(student.router)
1+
from app import app
222

233

244
@app.get("/")

0 commit comments

Comments
 (0)