APP/
ㄴ models.py --> 작업할 공간
class GuestBook(BaseMin, Base):
__tablename__ = "guestbook"
message = Column(String(255), nullable=False)
message_owner = Column(String(20), nullable=False)
owner_id = Column(Integer, ForeignKey("user.id"))
book_owner = relationship("User", back_populates="guestbooks")
from fastapi import Depends, APIRouter, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from sqlalchemy.orm.session import Session
from typing import List
from app.database import get_db
from .schema import GuestBookAdd, GuestBookReturn, GuestBookUpdate
from .service import addGuestBook, findAllGuestBook, updateGuestBook
router = APIRouter()
security = HTTPBearer()
# 방명록 작성
@router.post("", response_model=GuestBookReturn, status_code=status.HTTP_201_CREATED)
async def guestbook_add(
data: GuestBookAdd,
cred: HTTPAuthorizationCredentials = Depends(security),
db: Session = Depends(get_db),
):
return await addGuestBook(data, cred, db)
# 모든 방명록 조회
@router.get("", response_model=List[GuestBookReturn], status_code=status.HTTP_200_OK)
async def guestbook(db: Session = Depends(get_db)):
return await findAllGuestBook(db)
# 방명록 수정
@router.put("/{id}", response_model=GuestBookReturn, status_code=status.HTTP_202_ACCEPTED)
async def guestbook_update(
data: GuestBookUpdate,
id: int,
cred: HTTPAuthorizationCredentials = Depends(security),
db: Session = Depends(get_db),
):
return await updateGuestBook(data, id, cred, db)
@router.post("", response_model=GuestBookReturn, status_code=status.HTTP_201_CREATED)
async def guestbook_add(
data: GuestBookAdd,
cred: HTTPAuthorizationCredentials = Depends(security),
db: Session = Depends(get_db),
):
return await addGuestBook(data, cred, db)
addGuestBook
에서 받아온 정보를 GuestBookReturn 형태에 맞추어 반환한다.@router.get("", response_model=List[GuestBookReturn], status_code=status.HTTP_200_OK)
async def guestbook(db: Session = Depends(get_db)):
return await findAllGuestBook(db)
findAllGuestBook
에서 받아온 정보를 GuestBookReturn으로 이루어진 List 형태에 맞춰 반환한다.@router.put("/{id}", response_model=GuestBookReturn, status_code=status.HTTP_202_ACCEPTED)
async def guestbook_update(
data: GuestBookUpdate,
id: int,
cred: HTTPAuthorizationCredentials = Depends(security),
db: Session = Depends(get_db),
):
return await updateGuestBook(data, id, cred, db)
updateGuestBook
에서 받아온 정보를 GuestBookReturn 형태에 맞추어 반환한다. from ..user import utils
from .utils import add_guestbook, find_all_guestbook, update_guestbook
async def addGuestBook(data, cred, db):
decoded_dict = await utils.verify_user(cred)
return await add_guestbook(data, decoded_dict.get("id"), db)
async def findAllGuestBook(db):
return await find_all_guestbook(db)
async def updateGuestBook(data, id, cred, db):
decoded_dict = await utils.verify_user(cred)
return await update_guestbook(data.message, id, decoded_dict.get("id"), db)
async def addGuestBook(data, cred, db):
decoded_dict = await utils.verify_user(cred)
return await add_guestbook(data, decoded_dict.get("id"), db)
verify_user
함수에 받아온 토큰 값을 넣어 해독된 딕셔너리를 받아온다.add_guestbook
으로 메세지와 작성자를 DB에 저장한 뒤 반환한다.async def findAllGuestBook(db):
return await find_all_guestbook(db)
find_all_guestbook
에서 받은 정보를 반환한다.async def updateGuestBook(data, id, cred, db):
decoded_dict = await utils.verify_user(cred)
return await update_guestbook(data.message, id, decoded_dict.get("id"), db)
verify_user
함수에 받아온 토큰 값을 넣어 해독된 딕셔너리를 받아온다.update_guestbook
에서 방명록을 수정한 뒤 정보를 반환한다.from fastapi import HTTPException, status
from sqlalchemy import desc
from app.models import GuestBook
async def add_guestbook(data, id, db):
try:
row = GuestBook(message=data.message, owner_id=id, message_owner=data.message_owner)
db.add(row)
db.commit()
return row
except Exception as e:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail=f"{e} occured while adding guestbook",
)
async def find_all_guestbook(db):
return db.query(GuestBook).order_by(desc(GuestBook.created_at)).all()
async def update_guestbook(message, id, owner_id, db):
row = db.query(GuestBook).filter_by(id=id).first()
if row is None:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Guestbook Not Found",
)
if row.owner_id == owner_id:
row.message = message
db.commit()
else:
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="It's not owner")
return row
async def add_guestbook(data, id, db):
try:
row = GuestBook(message=data.message, owner_id=id, message_owner=data.message_owner)
db.add(row)
db.commit()
return row
except Exception as e:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail=f"{e} occured while adding guestbook",
)
async def find_all_guestbook(db):
return db.query(GuestBook).order_by(desc(GuestBook.created_at)).all()
sqlalchemy에서 쿼리문을 작성할 때 .order_by, .options, .offset, .limit 등으로 여러 옵션을 줘서 작성할 수 있다. desc() 옵션을 추가할 시 내부 인자를 기준으로 내림차순 정렬해서 반환해준다.
async def update_guestbook(message, id, owner_id, db):
row = db.query(GuestBook).filter_by(id=id).first()
if row is None:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Guestbook Not Found",
)
if row.owner_id == owner_id:
row.message = message
db.commit()
else:
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="It's not owner")
from pydantic import BaseModel
class GuestBookAdd(BaseModel):
message: str
message_owner: str
class GuestBookReturn(GuestBookAdd):
id: int
owner_id: int
class GuestBookUpdate(BaseModel):
message: str
지난 번과 마찬가지로 정의된 relationship을 가지고 회원 별 방명록 확인도 구현해보는 것도 재밌을 것이다.
[참고]
필자는 어차피 방명록인데 모두가 봐야하지 않나?는 생각에 전체 방명록만 불러오게 구현했다. 테이블 작성할 때 relationship이 적혀있는건 오늘 벨로그 글을 쓰게 되면서 알게 된 사실이다..
이번에도 Swagger로 보면 이렇게 잘 생성되어 있을 것이다!
이 때까지 글을 읽어준 독자님들께 감사하다고 말씀을 드리고 싶다. 이번 게시글까지 해서 현재 작성되어있는 API는 모두 업로드했다. 두 편 정도로 나누어 Test 코드 작성과 회고를 끝으로 이 시리즈를 마무리해보고자 한다.