-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbooks2.py
163 lines (135 loc) · 5 KB
/
books2.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
from email import header
from typing import Optional
from uuid import UUID
from fastapi import FastAPI,HTTPException,Request,status
from fastapi import Form, Header
from starlette.responses import JSONResponse
from models import Book,BookNoRating
app = FastAPI()
#Initilized the BOOKS=[] for adding books when read_all_boosk() is caled.
BOOKS=[]
class NegtiveNumberException(Exception):
"""
NegtiveNumberException is custom class for raising custom exception
"""
def __init__(self, books_to_return):
self.books_to_return=books_to_return
#Custom exception handler derived from NegtiveNumberException class
@app.exception_handler(NegtiveNumberException)
async def neg_number_exception_handler(request:Request, exception:NegtiveNumberException):
return JSONResponse(status_code=418,
content={"message":"Number of books cannot be negiteve"}
)
# New Status code incase of negtieve number as input.
# Custom error message for user
@app.get("/")
async def read_all_books(books_to_return:Optional[int]=None):
"""
If no book data is found, create_book_no_api() is invoked to initilized BOOKS list,
to help
"""
if len(BOOKS)<1:
create_book_no_api()
# Incase of negtieve number as input then custom exception is raised.
if books_to_return and books_to_return <0:
raise NegtiveNumberException(books_to_return=books_to_return)
if books_to_return and len(BOOKS)>=books_to_return>0:
i=1
newbooks=[]
while i<=books_to_return:
newbooks.append(BOOKS[i-1])
return newbooks
return BOOKS
# Searching book by UUID
# Initially UUID is fetched by running Get all books function, later UUID is fetched by calling /book/UUID
@app.get("/book/{book_id}")
async def read_book(book_id:Optional[UUID]):
for x in BOOKS:
if x.id==book_id:
return x
# When this api is called, it will not return rating to user.
# THis method is used to restrict some fields in case of response api.
# In this case we are restricitng the rating field in the response model.
@app.get("/book/rating/{book_id}",response_model=BookNoRating)
async def read_book_no_rating(book_id:Optional[UUID]):
for x in BOOKS:
if x.id==book_id:
return x
raise raise_item_cannot_be_foud_exception()
# Adding status code of 201 signifyis something is created
@app.post('/',status_code=status.HTTP_201_CREATED)
async def create_book(book:Book):
BOOKS.append(book)
return book
# Header class is used to create a custom header.
@app.post('/header')
async def read_header(random_head:Optional[str]=Header(None)):
return {"Random-Header":random_head}
# How to use form data username and password
@app.post("/book/login")
async def book_login(username:str=Form(),password:str=Form()):
return {'username':username,"password":password}
# How to use form data username and password
@app.post("/book/login/header/")
async def book_login_username_and_password_in_header(book_id: int,username:Optional[str]=Header(None),password:Optional[str]=Header(None)):
if username and password and username=="FastAPIUser" and password=="test1234":
#return {'username in header':username,"password in header":password}
return BOOKS[book_id-1]
else:
raise HTTPException(
status_code=404,
detail="user not found"
)
#Put Request
@app.put("/{book_id}")
async def update_book(book_id:UUID, book:Book):
counter=0
for x in BOOKS:
counter+=1
if x.id==book_id:
BOOKS[counter-1]=book
return BOOKS[counter-1]
raise_item_cannot_be_foud_exception()
#Delete Request by book_id
@app.delete('/{book_id}')
async def delete_book(book_id:UUID):
counter=0
for x in BOOKS:
counter+=1
if x.id==book_id:
del BOOKS[counter-1]
return f'book {book_id} deleted'
raise_item_cannot_be_foud_exception()
def create_book_no_api():
"""
This blocks appends the book data whenever server restarts just to have data to perfom validation of RestApi's
"""
book_1=Book(id="913302d8-0e41-43b8-86f4-a6e044714398",
title="title1",
author="author 1",
description='Descripton 1',
rating=90)
book_2=Book(id="113302d8-0e41-43b8-86f4-a6e044714398",
title="title2",
author="author 2",
description='Descripton 2',
rating=80)
book_3=Book(id="913304d8-0e41-43b8-86f4-a6e044714398",
title="title 3",
author="author 3",
description='Descripton 3',
rating=89)
book_4=Book(id="913332d8-0e41-43b8-86f4-a6e044714398",
title="title 4",
author="author 4",
description='Descripton 4',
rating=10)
BOOKS.append(book_1)
BOOKS.append(book_2)
BOOKS.append(book_3)
BOOKS.append(book_4)
#Exception Block for 404 book not found for updating and deleting
def raise_item_cannot_be_foud_exception():
raise HTTPException(status_code=404,
detail="Book Not Found",
headers={"X_header-Error":"Nothing to found for UUID"})