forked from mongodb-developer/mongodb-with-fastapi
-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.py
123 lines (95 loc) · 3.86 KB
/
app.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
import os
from fastapi import FastAPI, Body, HTTPException, status
from fastapi.responses import Response, JSONResponse
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel, Field, EmailStr
from bson import ObjectId
from typing import Optional, List
import motor.motor_asyncio
app = FastAPI()
client = motor.motor_asyncio.AsyncIOMotorClient(os.environ["MONGODB_URL"])
db = client.college
class PyObjectId(ObjectId):
@classmethod
def __get_validators__(cls):
yield cls.validate
@classmethod
def validate(cls, v):
if not ObjectId.is_valid(v):
raise ValueError("Invalid objectid")
return ObjectId(v)
@classmethod
def __modify_schema__(cls, field_schema):
field_schema.update(type="string")
class StudentModel(BaseModel):
id: PyObjectId = Field(default_factory=PyObjectId, alias="_id")
name: str = Field(...)
email: EmailStr = Field(...)
course: str = Field(...)
gpa: float = Field(..., le=4.0)
class Config:
allow_population_by_field_name = True
arbitrary_types_allowed = True
json_encoders = {ObjectId: str}
schema_extra = {
"example": {
"name": "Jane Doe",
"email": "[email protected]",
"course": "Experiments, Science, and Fashion in Nanophotonics",
"gpa": "3.0",
}
}
class UpdateStudentModel(BaseModel):
name: Optional[str]
email: Optional[EmailStr]
course: Optional[str]
gpa: Optional[float]
class Config:
arbitrary_types_allowed = True
json_encoders = {ObjectId: str}
schema_extra = {
"example": {
"name": "Jane Doe",
"email": "[email protected]",
"course": "Experiments, Science, and Fashion in Nanophotonics",
"gpa": "3.0",
}
}
@app.post("/", response_description="Add new student", response_model=StudentModel)
async def create_student(student: StudentModel = Body(...)):
student = jsonable_encoder(student)
new_student = await db["students"].insert_one(student)
created_student = await db["students"].find_one({"_id": new_student.inserted_id})
return JSONResponse(status_code=status.HTTP_201_CREATED, content=created_student)
@app.get(
"/", response_description="List all students", response_model=List[StudentModel]
)
async def list_students():
students = await db["students"].find().to_list(1000)
return students
@app.get(
"/{id}", response_description="Get a single student", response_model=StudentModel
)
async def show_student(id: str):
if (student := await db["students"].find_one({"_id": id})) is not None:
return student
raise HTTPException(status_code=404, detail=f"Student {id} not found")
@app.put("/{id}", response_description="Update a student", response_model=StudentModel)
async def update_student(id: str, student: UpdateStudentModel = Body(...)):
student = {k: v for k, v in student.dict().items() if v is not None}
if len(student) >= 1:
update_result = await db["students"].update_one({"_id": id}, {"$set": student})
if update_result.modified_count == 1:
if (
updated_student := await db["students"].find_one({"_id": id})
) is not None:
return updated_student
if (existing_student := await db["students"].find_one({"_id": id})) is not None:
return existing_student
raise HTTPException(status_code=404, detail=f"Student {id} not found")
@app.delete("/{id}", response_description="Delete a student")
async def delete_student(id: str):
delete_result = await db["students"].delete_one({"_id": id})
if delete_result.deleted_count == 1:
return Response(status_code=status.HTTP_204_NO_CONTENT)
raise HTTPException(status_code=404, detail=f"Student {id} not found")