※ 프로젝트 구조 예시
fastapi_project/ # 프로젝트 root 디렉토리
│
├── app/ #fast api 관련 api모음
│ ├── __init__.py
│ ├── main.py # 여기서 app= FastAPI()를 선언한다. web framework의 시작점
│ ├── api/
│ │ ├── __init__.py
│ │ ├── endpoints/ #endpoint로 crud의 명령어가 어느 url로 갈지 정한다. api/와 같은 트리 레벨에서 router로 사용되는 경우도 많다
│ │ │ ├── __init__.py
│ │ │ ├── items.py #예시
│ │ │ └── users.py #예시
│ ├── core/ #django에서 setting에 해당하는 부분 프레임워크에 필요한 middleware 혹은 db를 설정하는 곳
│ │ ├── __init__.py
│ │ ├── config.py
│ ├── models/ # orm에서 model을 맡는 부분
│ │ ├── __init__.py
│ │ ├── user.py
│ │ └── item.py
│ ├── crud/ # model에서 만들어진 객체를 schema를 이용하여 crud 명령어 구현
│ │ ├── __init__.py
│ │ ├── user.py
│ │ └── item.py
│ ├── schemas/ # model에 바로 웹에서 접근하는 것이 아닌 일종의 validation역할을 하는 부분 여기를 통해 model과 crud를 연결한다.
│ │ ├── __init__.py
│ │ ├── user.py
│ │ └── item.py
│ ├── db/ # db instance를 관리하는 부분
│ │ ├── __init__.py
│ │ ├── base.py # DB의 common model로 쓰일 base모델을 정의
│ │ └── session.py # db와 통신하는 엔진, 세션을 정의 그리고 db와 종속성 주입을 하는 함수를 정의
│ ├── tests/ # test코드
│ ├── __init__.py
│ ├── test_items.py
│ └── test_users.py
│
├── .env
├── .gitignore
├── requirements.txt #가상환경
├── alembic.ini
├── README.md
└── alembic/
├── env.py # alembic orm 의 설정 파일
├── script.py.mako
└── versions/ # alembic orm의 migration 관리
1. Main app 작성
- FastAPI 인스턴스 할당
- 가장 마지막에 router 작성 (django에서 root urls.py의 역할을 한다
2. Config 작성
- database url 및 어떤 db를 쓸지 엔진을 설정
- db종속성을 담당하는 Base모델을 이곳에서 정의해도 되고 db/database.py 와 db/session.py에 나눠서 작성해도 좋다
3. Model 작성
- config 혹은 db/database에서 common 모델을 불러와 그걸 기반으로 모델을 만든다
class Item(Base):
__tablename__ = "items"
id = Column(Integer, primary_key=True, index=True)
title = Column(String, index=True)
description = Column(String, index=True)
4. Schema 작성
- 외부에서 바로 db에 접속하는것이 아니라 스키마에 거쳐 validation을 확인한다.
- 각 스키마의 Request, Response를 정의한다. (이 부분은 나중에 General한 request, response로 바꾸는걸 추천한다)
from typing import List, Optional, Generic, TypeVar
from pydantic import BaseModel, Field
T = TypeVar("T")
class ItemSchema(BaseModel):
id: Optional[int] = None
title: Optional[str] = None
description: Optional[str] = None
class Config:
from_attributes = True
class Request(BaseModel, Generic[T]):
parameter: Optional[T] = Field(...)
class RequestItem(BaseModel):
parameter: ItemSchema = Field(...)
class Response(BaseModel, Generic[T]):
code: str
status: str
message: str
result: Optional[T] = None
5. CRUD
- db에서 데이터를 불러온다 단 create update 같은 경우 schema를 통해 접근한다.
from sqlalchemy.orm import Session
from models.item import Item
from schemas.item import ItemSchema
def get_item(db: Session, skip: int = 0, limit: int = 100):
return db.query(Item).offset(skip).limit(limit).all()
def get_item_by_id(db: Session, book_id: int):
return db.query(Item)
def create_item(db: Session, item: ItemSchema):
_item = Item(title=item.title, description=item.description)
db.add(_item)
db.commit()
db.refresh(_item)
return _item
def remove_book(db: Session, item_id: int):
_item = get_item_by_id(db=db, item_id=item_id)
db.delete(_item)
db.commit()
def update_book(db: Session, item_id: int, title: str, description: str):
_item = get_item_by_id(db=db, item_id=item_id)
_item.title = title
_item.description = description
db.commit()
db.refresh(_item)
return _item
6. Router(혹은 api/endpoint)작성
- api의 밑 디렉토리 endpoint로 할거면 api/v1/endpoint로 하는걸 추천 한다. api의 버전을 관리하는 방법 중 하나다.
- app.get과 router.get의 차이는 중앙에서 관리하는가 모듈에서 관리하는가 차이
참고 - https://expressjs.com/ko/guide/routing.html
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from crud import item as crud_item
from db.session import get_db
from schemas import item as schemas_item
router = APIRouter()
@router.get("/")
async def read_items(skip: int = 0, limit: int = 10, db: Session = Depends(get_db)):
_item = crud_item.get_item(db, skip=skip, limit=limit)
return schemas_item.Response(
code="200", status="ok", message="Item read successfully", result=_item
).model_dump()
@router.post("/create")
async def create_item(request: schemas_item.RequestItem, db: Session = Depends(get_db)):
crud_item.create_item(db, item=request.parameter)
return schemas_item.Response(
status="Ok", code="200", message="Item created successfully"
)
7. 마무리
- main 함수로 가서 router를 등록한다
app.include_router(items.router, prefix="/item", tags=["item"])
'python' 카테고리의 다른 글
Stable Diffusion 3 API 가지고 놀기 (3) | 2024.09.27 |
---|---|
poetry add 혹은 pipenv install 무한로딩 (0) | 2024.05.08 |
class 적응하기 2 (0) | 2024.01.30 |
class 적응하기 1 (0) | 2024.01.30 |
Class method vs Static method in python (2) | 2024.01.03 |