본문 바로가기
Projects/Project Zero

Project Zero 3. DRF ViewSet

by mintropy 2022. 9. 8.

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 공식문서의 다음 내용을 참조할 수 있다.

 

django.contrib.auth | Django documentation | Django

Django The web framework for perfectionists with deadlines. Overview Download Documentation News Community Code Issues About ♥ Donate

docs.djangoproject.com

생각정리

 이 부분은 정말 간단하고, 어쩌면 유저 관련 내용이다보니 프로젝트 초기에 설정하고 관심도 가지지 않았던 경우가 많았던 것 같다. 천천히 하나하나씩 작성하다 보니 어떤 문제점들이 있고 어떻게 해결해야 할지 더 기게 고민할 수 있는 것 같아 좋은 것 같다. 그것이 이 프로젝트를 진행하는 목표 중 하나이기도 했기 때문에 한편으로는 느리더라도 좋은 방향성이라고 생각한다.

 

'Projects > Project Zero' 카테고리의 다른 글

Project Zero 2. react-router-dom  (2) 2022.09.07
Project Zero 1. 프로젝트의 시작  (0) 2022.09.04

댓글