구조화란 애플리케이션 컴포넌트를 형식에 맞춰 정리하는 것이다.
형식을 모듈이라고 하며, 모듈화는 애플리케이션 코드와 콘텐츠의 가독성을 높여준다.
이벤트 플래너 만들기.
이벤트 플래너 애플리케이션 설계:
등록된 사용자는 이벤트를 추가, 변경, 삭제할 수 있으며 애플리케이션이 자동으로 만든 이벤트 페이지에서 생성된 이벤트를 확인할 수 있다.
등록된 사용자와 이벤트는 모두 고유한 ID를 갖는다.
애플리케이션의 첫 단계는 이벤트 모델과 사용자 모델을 정의하는 것이다. 이 모델들은 데이터가 어떤 방식으로 입력 및 저장되고 애플리케이션에 표현되는지를 정의한다.
각 사용자는 Events 필드를 가지며 여러 개의 이벤트를 저장할 수 있다.
이벤트 모델(Event)을 models 폴더의 events.py에 정의:
class Event(BaseModel):
id: int // 자동 생성되는 고유 식별자
title: str // 이벤트 타이틀
image: str // 이벤트 이미지 배너의 링크
description: str // 이벤트 설명
tags: List[str] // 그룹화를 위한 이벤트 태그
location: str // 이벤트 위치
class Config:
schema_extra = {
"example": {
"title": "Fast API Book Launch",
"image": "https://linktomyimage.com/image.png",
"description": "We will be discussing the contents of the FastAPI book in this event. Ensure to come with your own copy to win gifts!",
"tags": ["python", "fastapi", "book", "launch"],
"location": "Google Meet"
}
}
from pydantic import BaseModel, EmailStr
from typing import Optional, List
from models.events import Event
class User(BaseModel):
email: EmailStr
password: str
events: Optional[List[Event]]
Config 서브 클래스 추가
UserSignIn 모델 생성
사용자 라우트는 로그인, 로그아웃, 등록으로 구성된다.
인증을 완료한 사용자는 이벤트를 생성, 변경, 삭제할 수 있으며, 인증을 거치지 않은 사용자는 생성된 이벤트를 확인하는 것만 가능하다.
routes 폴더의 users.py에 구현
1. /signup 라우트 정의:
from fastapi import APIRouter, HTTPException, status
from models.users import User, UserSignIn
user_router = APIRouter(
tags=["User"],
)
users = {}
@user_router.post("/signup")
async def sign_new_user(data: User) -> dict:
if data.email in users:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
detail="User with supplied username exists"
)
users[data.email] = data
return {
"message": "User successfully registered!"
}
@user_router.post("/signin")
async def sign_user_in(user: UserSignIn) -> dict:
if user.email not in users:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User does not exist"
)
if users[user.email].password != user.password:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Worng credentials passed"
)
return {
"message": "User signed in successfully."
}
from fastapi import FastAPI
from routes.users import user_router
import uvicorn
app = FastAPI()
app.include_router(user_router, prefix="/user")
if __name__ == "__main__":
uvicorn.run("main:app", host="127.0.0.1", port=8000, reload=True)
python main.py
curl -X 'POST' 'http://127.0.0.1:8000/user/signup' -H 'accept: application/json' -H 'Content-Type: application/json' -d '{ "email": "fastapi@packt.com", "password": "strong!!!", "events": []}'
curl -X 'POST' 'http://127.0.0.1:8000/user/signin' -H 'accept: application/json' -H 'Content-Type: application/json' -d '{ "email": "fastapi@packt.com", "password": "strong!!!" }'
from fastapi import APIRouter, Body, HTTPException, status
from models.events import Event
from typing import List
event_router = APIRouter(
tags=["Events"]
)
events = []
@event_router.get("/", response_model=List[Event])
async def retrieve_all_event() -> List[Event]:
return events
@event_router.get("/{id}", response_model=Event)
async def retrieve_event(id: int) -> Event:
for event in Event:
if event.id == id:
return event
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Event with supplied ID does not exist"
)
@event_router.post("/new")
async def create_event(body: Event = Body(...)) -> dict:
events.append(body)
return{
"message": "Event created successfully."
}
@event_router.delete("/{id}")
async def delete_event(id: int) -> dict:
for event in events:
if event.id == id:
events.remove(event)
return{
"message": "Event deleted successfully."
}
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Event with supplied ID does not exist"
)
@event_router.delete("/")
async def delete_all_event() -> dict:
events.clear()
return{
"message": "Event deleted successfully."
}
from routes.events import event_router
app.include_router(event_router, prefix="/event")
curl -X 'GET' 'http://127.0.0.1:8000/event/' -H 'accept: application/json'
curl -X 'POST' 'http://127.0.0.1:8000/event/new' -H 'accept: application/json' -H 'Content-Type: application/json' -d '{ "id": 1, "title": "Launch", "image": "https://linktomyimage.com/image.png", "description": "event", "tags": ["python", "fastapi", "book", "launch"], "location": "Google Meet" }'
curl -X 'GET' 'http://127.0.0.1:8000/event/1' -H 'accept: application/json'
curl -X 'DELETE' 'http://127.0.0.1:8000/event/1' -H 'accept: application/json'