[FastAPI] 구조화

귤티·2024년 5월 8일
0

FastAPI

목록 보기
5/10

구조화란 애플리케이션 컴포넌트를 형식에 맞춰 정리하는 것이다.
형식을 모듈이라고 하며, 모듈화는 애플리케이션 코드와 콘텐츠의 가독성을 높여준다.

애플리케이션 구조화

이벤트 플래너 만들기.
이벤트 플래너 애플리케이션 설계:
업로드중..

  • routes 폴더
    - events.py: 이벤트 생성, 변경, 삭제 등의 처리를 위한 라우팅
    • users.py: 사용자 등록 및 로그인 처리를 위한 라우팅
  • models 폴더
    - events.py: 이벤트 처리용 모델을 정의
    • users.py: 사용자 처리용 모델을 정의

이벤트 플래너 애플리케이션

등록된 사용자는 이벤트를 추가, 변경, 삭제할 수 있으며 애플리케이션이 자동으로 만든 이벤트 페이지에서 생성된 이벤트를 확인할 수 있다.

등록된 사용자와 이벤트는 모두 고유한 ID를 갖는다.

모델 구현

  1. 애플리케이션의 첫 단계는 이벤트 모델과 사용자 모델을 정의하는 것이다. 이 모델들은 데이터가 어떤 방식으로 입력 및 저장되고 애플리케이션에 표현되는지를 정의한다.
    각 사용자는 Events 필드를 가지며 여러 개의 이벤트를 저장할 수 있다.

  2. 이벤트 모델(Event)을 models 폴더의 events.py에 정의:

class Event(BaseModel):
    id: int // 자동 생성되는 고유 식별자
    title: str // 이벤트 타이틀
    image: str // 이벤트 이미지 배너의 링크
    description: str // 이벤트 설명
    tags: List[str] // 그룹화를 위한 이벤트 태그
    location: str // 이벤트 위치
  1. 이벤트 클래스 안에 Config 서브 클래스 추가:
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"
        }
    }
  1. 사용자 모델(User)을 models 폴더의 users.py 파일에 정의:
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]]
  1. Config 서브 클래스 추가

  2. 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!"
    }
  1. /signin 라우트 구현:
@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."
    }
  1. main.py에 라우트 등록
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)
  1. 실행:
python main.py
  1. 사용자 등록 테스트:
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": []}'
  1. 로그인 테스트:
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!!!" }'

이벤트 라우트 구현

  1. routes 폴더의 events.py에 이벤트 라우트 정의
from fastapi import APIRouter, Body, HTTPException, status
from models.events import Event
from typing import List

event_router = APIRouter(
    tags=["Events"]
)

events = []
  1. 모든 이벤트를 추출하거나 특정 ID의 이벤트만 추출하는 라우트 정의
@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"
    )
  1. 이벤트 생성 및 삭제 라우트 정의:

@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."
    }
  1. main.py에 라우트 설정 변경:
from routes.events import event_router

app.include_router(event_router, prefix="/event")
  1. 라우트 테스트:
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'
profile
취준 진입

0개의 댓글

관련 채용 정보