ViewSet
ViesSet은 DRF에서 비슷한 연관된 view 클래스를 하나의 클래스로 구현한 것으로 다른 프레임워크에서 Resources 또는 Controllers라고 부르기도 한다. 독특한 점은 class-based view의 한 종류로, 메서드 핸들러를 제공하지 않아서 라우터를 지정하는 .get(), .post() 대신 .list(), .create()를 제공한다는 점이다. DefaultRouter()를 활용하여 자동적으로 라우팅 할 수 있고, .as_view()를 통하여 지정할 수도 있다.
추가적인 장점으로 queryset을 지정하여 여러 view의 유사한 로직을 묶을 수 있고, 라우터를 지정할 때 URL conf를 신경 쓸 필요 없으며, 추가적인 라우터를 사용할 때, @action데코레이터를 활용할 수 있음
@action데코레이터에서 detail=True를 통하여 세부동작을 지정할 수 있고, .as_view()를 따로 지정하지 않아도 됨
ViewSet기본 설정
from rest_framework.response import Response
from rest_framework.viewsets import ViewSet
from rest_framework.views import status
from .models import User
# Create your views here.
class UserViewSet(ViewSet):
def signup(self, request):
data = {"username": "admin"}
return Response(data=data, status=status.HTTP_201_CREATED)
def retrieve_profile(self, request):
data = {
"username": "admin",
"email": "smaple@smaple.com",
"blogs": ["sample blog name"],
}
return Response(data=data, status=status.HTTP_200_OK)
def update_profile(self, request):
data = {
"username": "admin",
"email": "smaple@smaple.com",
"blogs": ["sample blog name"],
}
return Response(data=data, status=status.HTTP_201_CREATED)
DRF의 ViewSet을 상속받는 UserViewSet을 생성했다. 유저와 관련한 동작은 이 클래스가 담당할 것이다. 회원가입, 유저 정보 조회, 유저 정보 수정에 대한 API와 더미 데이터 반환을 위한 코드를 작성했다. 각 함수 이름은 DRF에서 주어지는 액션을 사용해도 되지만, 나는 위와 같이 이해할 수 있는 방향으로 작성하고, 라우팅을 지정하는 것을 선호한다.
모두 수동으로 라우팅을하면 그냥 CBV, FBV를 사용해도 되는 것이 아닌가라는 의문이 있을 수 있지만, ViewSet에서 추가적으로 제공하는 기능 그리고 추가적인 라이브러리 등을 활용할 때 모든 API에 동시에 적용될 수 있는 장점이 있다. 관련해서는 나중에 다시 다루어 볼 것 같다.
그러면 세 개의 API를 하나하나씩 상세하게 설계해보자.
serializer
from rest_framework import serializers
from .models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = "__all__"
우선 serializer를 구성했다. serializer관련 내용은 다음 게시글로 다룰 예정인데, 간단하게 설명하면, 특정 모델이나 필드 설정에 대하여 입력받은 데이터의 검증과 렌더링에 도움을 준다.
signup
def signup(self, request):
data = {
"username": request.data.get("username", ""),
"password": request.data.get("password", ""),
}
serialzier = UserSerializer(data=data)
if serialzier.is_valid():
serialzier.save()
return Response(data=serialzier.data, status=status.HTTP_201_CREATED)
return Response(data=serialzier.errors, status=status.HTTP_400_BAD_REQUEST)
회원가입은 최소한의 정보를 받아서 처리하도록 했다. username, password를 입력받고, serializer를 통하여 검증한다. 지금은 별다른 검증이 없기때문에 비어있는 값이 아니거나 중복되는 username이 아닌 경우라면 통과된다. 회원가입에 필요한 항목 및 username, password의 검증은 serializer를 다루며 한 한 층 강화할 것이다.
profile
def retrieve_profile(self, request):
user = request.user
if user.is_anonymous:
return Response(status=status.HTTP_401_UNAUTHORIZED)
serializer = UserSerializer(instance=user)
return Response(serializer.data, status=status.HTTP_200_OK)
def update_profile(self, request):
user = request.user
if user.is_anonymous:
return Response(status=status.HTTP_401_UNAUTHORIZED)
data = {
"username": user.username,
"password": user.password,
"email": request.data.get("email", ""),
}
serializer = UserSerializer(instance=user, data=data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
유저 프로필은 조회와 수정만 생성했다. 이 두 API는 유저정보가 필요하게 되는데, request.user
를 활용하여 유저 객체를 가져오고, 만약 익명 유저(데이터베이스에 등록되지 않은 유저)라면 인증되지 않음을 의미하는 401을 반환한다.
프로필 조회는 위에서 설명한 serializer를 활용하여 데이터를 반환하고, 수정하는 경우는 입력받은 데이터를 활용해서 수정 및 반환한다. is_anonymous
와 관련된 내용은 Django 공식문서의 다음 내용을 참조할 수 있다.
생각정리
이 부분은 정말 간단하고, 어쩌면 유저 관련 내용이다보니 프로젝트 초기에 설정하고 관심도 가지지 않았던 경우가 많았던 것 같다. 천천히 하나하나씩 작성하다 보니 어떤 문제점들이 있고 어떻게 해결해야 할지 더 기게 고민할 수 있는 것 같아 좋은 것 같다. 그것이 이 프로젝트를 진행하는 목표 중 하나이기도 했기 때문에 한편으로는 느리더라도 좋은 방향성이라고 생각한다.
'Projects > Project Zero' 카테고리의 다른 글
Project Zero 2. react-router-dom (2) | 2022.09.07 |
---|---|
Project Zero 1. 프로젝트의 시작 (0) | 2022.09.04 |
댓글