2024-08-22 THU
0. 라이브러리(main.py) / 준비
from fastapi import FastAPI, Path, HTTPException, status, Body, Request, Form
from fastapi.encoders import jsonable_encoder
from fastapi.responses import RedirectResponse
from fastapi.templating import Jinja2Templates
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel, Field
from typing import Optional, List, Dict
from starlette.responses import HTMLResponse
from starlette.status import HTTP_400_BAD_REQUEST
from database import cars
-1) fastapi
-2) pydantic
-3) Form
-4) Path, HTTPException, status, Body, Request
-5) jsonable_encoder
-6) RedirectResponse
-7) Jinja2Template
-8) StaticFiles
-9) BaseModel, Field
-10) Optional, List, Dict
-11) HTMLResponse
-12) HTTP_400_BAD_REQUEST
-13) database
templates = Jinja2Templates(directory="templates")
app = FastAPI()
app.mount("/static", StaticFiles(directory="static"), name="static")
class Car(BaseModel): # Car 모델 정의
make: Optional[str]
model: Optional[str]
year: Optional[int] = Field(..., ge=1970, lt=2022) # 1970년 이상 2022년 미만의 값만 허용
price: Optional[float]
engine: Optional[str] = "V4"
autonomous: Optional[bool]
sold: Optional[List[str]]
engine: Optional[str] = "V4" : default값이 "v4"라는 뜻. 입력하지 않으면 기본적으로 v4 할당1. main.py
@app.get("/", response_class = RedirectResponse)
def read_root(request: Request):
return RedirectResponse(url="/cars")
@app.get("/cars", response_class = HTMLResponse)
def get_cars(request: Request, number: Optional[str] = Query("10", max_length = 3)):
response = []
for id, car in list(cars.items())[:int(number)]:
response.append((id, car))
return templates.TemplateResponse("index.html", {"request": request, "cars": response, "title":'Home'})
__ get 엔드포인트 "/cars" 설명
request: Request 현재 http 요청 객체이고, number: Optional[str] = Query~~) 쿼리 파라미터로 기본값은 10, 최대 길이는 3자이다..items 메서드로 각 자동차 정보를 가져와서 각 자동차의 id:car를 쌍으로 response 리스트에 담는다.@app.post("/search", response_class = RedirectResponse)
def search_cars(id: str = Form(...)):
return RedirectResponse(url ="/cars/"+id, status_code=302)
@app.get("/cars/{id}", response_class = HTMLResponse)
def get_car_by_id(request: Request, id: int = Path(..., ge = 0, lt = 1000)): #greater than, less than
car = cars.get(id)
response = templates.TemplateResponse("search.html", {"request": request, 'car': car, 'title':'Search Car'})
if not car:
response.status_code = status.HTTP_404_NOT_FOUND
return response
cars.get(id) : get 메서드는 없는 id 값이 들어와도 오류 발생시키지 않음@app.get("/create", response_class=HTMLResponse)
def create_car(request: Request):
return templates.TemplateResponse("create.html", {"request": request, "title": "Create Car"})
@app.post("/cars", status_code=status.HTTP_201_CREATED)
def add_cars(
make: Optional[str] = Form(...),
model: Optional[str] = Form(...),
year: Optional[str] = Form(...),
price: Optional[str] = Form(...),
engine: Optional[str] = Form(...),
autonomous: Optional[bool] = Form(...),
sold: Optional[str] = Form(None),
min_id: Optional[int] = Body(0),
):
# year 값을 정수로 변환
try:
year = int(year) if year is not None else None
except ValueError:
raise HTTPException(status_code=HTTP_400_BAD_REQUEST, detail="Year must be an integer.")
# sold 값을 리스트로 변환
if sold is not None:
sold = [sold] if isinstance(sold, str) else sold #isinstance: sold가 str이면 [sold]로 변환
body_cars = [Car(make=make, model=model, year=year, price=price, engine=engine, autonomous=autonomous, sold=sold)]
if len(body_cars) < 1:
raise HTTPException(status_code=HTTP_400_BAD_REQUEST, detail="No cars to add.")
min_id = len(cars) + 1 # 다음 ID를 계산
for car in body_cars:
while cars.get(min_id):
min_id += 1
cars[min_id] = jsonable_encoder(car)
min_id += 1
return RedirectResponse(url="/cars", status_code=302)
def add_cars(....) 함수는 매개변수를 Form 형태로 make ~ min_id까지 받는다.🍀clova says🍀
예를들어 입력할 때 "2010년"이라고 쓰는 사람이 있음
그러면 처음부터 int로 받아버리면 오류남
그래서 str로 받아서 아래 try에서 처럼 int(year)로 바꿔주면 "2010년" 중에 2010만 뽑아와서 year 변수에 저장한다~!~!
수업내내 궁금했는데 해결 완료 ><
@app.get("/edit", response_class=HTMLResponse)
def edit_car(request: Request, id: int = Query(...)):
car = cars.get(id)
if not car:
return templates.TemplateResponse("search.html", {"request": request, "id": id, "car": car, "title": "Edit Car"}, status_code=status.HTTP_404_NOT_FOUND)
return templates.TemplateResponse("edit.html", {"request": request, "id": id, "car": car, "title": "Edit Car"}) # 템플릿 응답 반환
@app.post("/cars/{id}")
def update_car(request: Request, id: int,
make: Optional[str] = Form(None),
model: Optional[str] = Form(None),
year: Optional[str] = Form(None),
price: Optional[float] = Form(None),
engine: Optional[str] = Form(None),
autonomous: Optional[bool] = Form(None),
sold: Optional[str] = Form(None),
):
stored = cars.get(id)
if not stored:
return templates.TemplateResponse("search.html", {"request": request, "id": id, "car": stored, "title": "Edit Car"}, status_code=status.HTTP_404_NOT_FOUND)
try:
year = int(year) if year is not None else stored['year']
except ValueError:
raise HTTPException(status_code=HTTP_400_BAD_REQUEST, detail="Year must be an integer.")
# sold 값을 리스트로 변환
if sold is not None:
sold = [sold] if isinstance(sold, str) else sold
updated_data = Car(
make=make or stored.get('make'),
model=model or stored.get('model'),
year=year,
price=price if price is not None else stored.get('price'),
engine=engine or stored.get('engine'),
autonomous=autonomous if autonomous is not None else stored.get('autonomous'),
sold=sold or stored.get('sold')
)
cars[id] = jsonable_encoder(updated_data)
return RedirectResponse(url="/cars", status_code=302)
stored = cars.get(id) 이부분이 살짝 이해가 잘 안되는데... 나의 궁금증!sold = [sold] if isinstance(sold, str) else sold : sold가 str이면 리스트로 변환하고, 아니면 그냥 sold 그 자체로 반환updated_data = Car( 어쩌구 저쩌구 ) : 복잡해 보이지만 사용자가 업데이트 한 정보 or 원래 정보를 조합 해서 edit 한다는 뜻cars[id] = jsonable_encoder(updated_data) : jsonable_encoder 함수를 사용해서 updated_data를 JSON 형식으로 변환하고 cars 딕셔너리에 id 키와 함께 저장한다~!@app.get("/delete/{id}", response_class=RedirectResponse)
def delete_car(request: Request, id: int = Path(...)):
if not cars.get(id):
return templates.TemplateResponse("search.html", {"request": request, "id": id, "title": "Edit Car"}, status_code=status.HTTP_404_NOT_FOUND)
del cars[id]
return RedirectResponse(url="/cars")
2. database.py
cars = {
1: {
"make": "CarBrand",
"model": "Fast",
"year": 1998,
"price": 25000.0,
"engine": "V8",
"autonomous": False,
"sold": ["NA","EU"]
},
2: {
"make": "Speedy",
"model": "FourWheeler SUV",
"year": 2021,
"price": 55400.0,
"engine": "V4",
"autonomous": False,
"sold": ["AF","AN","AS","EU","NA","OC","SA"]
},
3: {
"make": "Elektrik",
"model": "AutoCar",
"year": 2019,
"price": 45000.0,
"engine": "V8",
"autonomous": True,
"sold": ["AS"]
},
4: {
"make": "CarBrand",
"model": "Beetle",
"year": 2004,
"price": 21299.99,
"engine": "V4",
"autonomous": False,
"sold": []
},
5: {
"make": "CarPro",
"model": "Supersonic",
"year": 2015,
"price": 215000.0,
"engine": "V12",
"autonomous": False,
"sold": ["NA","AF","OC","SA"]
},
6: {
"make": "Ham",
"model": "hanny",
"year": 1998,
"price": 'INF',
"engine": "V12",
"autonomous": False,
"sold": ["NA","AF","OC","SA"]
}
}




2. 딥러닝 + 웹 _ dog breed predict
3. 딥러닝 + 웹 _ face detect