DB에 접속하는 부분과 실제 처리하는 부분을 분리하여 코딩함
- 스프링 부트는 처음부터 이렇게 되어 있어서, 분리하는 장점을 체험하기가 힘듬...
main.py
from decouple import config
from fastapi import FastAPI
from motor.motor_asyncio import AsyncIOMotorClient
from fastapi.middleware.cors import CORSMiddleware
from routers.car import router as car_router
origins = [
"http://localhost:3000",
]
DB_URL = config('DB_URL', cast=str)
DB_NAME = config('DB_NAME', cast=str)
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins = origins,
allow_credentials = True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.on_event("startup")
async def startup_db_client():
app.mongodb_client = AsyncIOMotorClient(DB_URL)
app.mongodb = app.mongodb_client[DB_NAME]
@app.on_event("shutdown")
async def shutdown_db_client():
app.mongodb_client.close()
app.include_router(car_router, prefix="/cars")
routers/car.py
from fastapi import FastAPI, Body, HTTPException, status, APIRouter, Request
from typing import Dict, List
from fastapi.encoders import jsonable_encoder
from fastapi.responses import JSONResponse
from bson import ObjectId
from models import CarBase, CarUpdate
router = APIRouter()
@router.get("/{id}")
async def root(
request: Request,
id:str):
if (car := await request.app.mongodb["cars"].find_one({"_id": ObjectId(id)})) is not None:
return get_ids(car)
raise HTTPException(status_code=404, detail=f"Car with {id} not found")
# car = await app.mongodb["cars"].find_one({"_id": ObjectId(id)})
# # print(car)
# return get_ids(car)
@router.get("/")
async def list_all_cars(
request: Request,
min_price: int=0,
max_price: int=100000,
brand:str=None,
page:int=1):
RESULT_PER_PAGE = 25
skip = (page - 1) * RESULT_PER_PAGE
query = {"price": {"$lte":max_price, "$gte":min_price}}
if brand:
query["brand"] = brand
list = request.app.mongodb["cars"].find(query).sort("_id", -1).skip(skip).limit(RESULT_PER_PAGE)
result = [get_ids(car) async for car in list]
return result
def get_ids(car: Dict) -> Dict:
# print(car)
id = car["_id"]
car["_id"] = str(id)
return car
@router.post("/")
async def new_car( request: Request, car: CarBase = Body(...)):
# print(car)
car = jsonable_encoder(car)
new_car = await request.app.mongodb["cars"].insert_one(car)
# print(new_car)
# print(new_car.inserted_id)
created_car = await request.app.mongodb["cars"].find_one({"_id": ObjectId(new_car.inserted_id)})
#return {"message": "new_car created"}
return JSONResponse(status_code=status.HTTP_201_CREATED, content=get_ids(created_car))
@router.put("/{id}")
async def update_car(request: Request, id: str, car: CarUpdate = Body(...)):
print(car.model_dump())
await request.app.mongodb["cars"].update_one(
{"_id": ObjectId(id)}, {"$set": car.model_dump()}
)
if (car := await request.app.mongodb["cars"].find_one({"_id": ObjectId(id)})) is not None:
return get_ids(car)
raise HTTPException(status_code=404, detail=f"Car with {id} not found")
@router.delete("/{id}")
async def delete_car(request: Request, id: str):
delete_result = await request.app.mongodb["cars"].delete_one({"_id": ObjectId(id)})
if (delete_result.deleted_count == 1):
return JSONResponse(status_code=status.HTTP_204_NO_CONTENT, content=None)
raise HTTPException(status_code=404, detail=f"Car with {id} not found")
이렇게 하면 FastAPI관련된 것은 전부 main.py에 두고 리퀘스트로 참조만 가능하다...