Python Django 강좌 : 제 6강 - View

Python Django ViewSet

Python Django 강좌 : 제 6강 - View
[ Python-Django ] - 윤대희

Django View


장고에서 뷰는 어떤 데이터를 표시할지 정의하며, HTTP 응답 상태 코드(response)를 반환합니다.

views.py 파일에 애플리케이션의 처리 논리를 정의합니다.

사용자가 입력한 URL에 따라, 모델(Model)에서 필요한 데이터를 가져와 뷰에서 가공해 보여주며, 템플릿(Template)에 전달하는 역할을 합니다.

장고의 뷰 파일(views.py)은 요청에 따른 처리 논리를 정의합니다.

즉, 사용자가 요청하는 값(request)을 받아 모델과 템플릿을 중개하는 역할을 합니다.


views.py


from django.core.exceptions import *
from rest_framework import status
from rest_framework import viewsets
from rest_framework.response import Response
from first_app.models import UserModel
from first_app.serializers import UserSerializer

# Create your views here.
class UserViewSet(viewsets.ModelViewSet):
    queryset = UserModel.objects.all()
    serializer_class = UserSerializer
    
    def get_queryset(self):
        return UserModel.objects.all()
    
    def create(self, request, *args, **kwargs):
        serializer = UserSerializer(data=request.data)
        if serializer.is_valid(raise_exception=False):
            serializer.save()
            return Response({"message": "Operate successfully"}, status=status.HTTP_201_CREATED)
        else:
            return Response({"message": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)

    def list(self, request):
        # queryset = UserModel.objects.all()
        # serializer = UserSerializer(queryset, many=True)
        serializer = UserSerializer(self.get_queryset(), many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

    def retrieve(self, request, uuid=None):
        try:
            objects = UserModel.objects.get(id=uuid)
            serializer = UserSerializer(objects)
            return Response(serializer.data, status=status.HTTP_200_OK)
        except ObjectDoesNotExist:
            return Response({"message": "존재하지 않는 UUID({})".format(uuid)}, status=status.HTTP_404_NOT_FOUND)

    def update(self, request, uuid=None):
        objects = UserModel.objects.get(id=uuid)
        serializer = UserSerializer(objects, data=request.data)
        if serializer.is_valid(raise_exception=False):
            serializer.save()
            return Response({"message": "Operate successfully"}, status=status.HTTP_200_OK)
        else:
            return Response({"message": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)

    def destroy(self, request, uuid=None):
        objects = UserModel.objects.get(id=uuid)
        objects.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

뷰(views.py) 파일을 위와 같이 정의합니다.

DRF에서는 ViewSet이라는 추상 클래스를 제공합니다.

ViewSet 클래스는 get()이나 post() 같은 메서드를 제공하지는 않지만, create()list() 같은 메서드를 지원합니다.

ViewSet 클래스는 URL 설정을 통해서 간단하게 연결할 수 있습니다.



Module


from django.core.exceptions import *
from rest_framework import status
from rest_framework import viewsets
from rest_framework.response import Response
from first_app.models import UserModel
from first_app.serializers import UserSerializer

from django.core.exceptions import *은 장고에서 사용하는 예외 사항을 가져옵니다. 와일드카드(*)를 사용해서 모든 예외 사항을 등록합니다.

from rest_framework import statusHTTP 상태 코드(status)를 등록합니다. 1xx(조건부 응답)이나 2xx(성공) 등을 반환할 수 있습니다.

from rest_framework import viewsets은 views.py에서 사용할 뷰 클래스입니다.

from rest_framework.response import Response는 응답에 사용할 TemplateResponse 형식의 객체입니다. 이를 통해 클라이언트에게 제공할 콘텐츠 형태로 변환합니다.

from first_app.models import UserModelmodels.py에서 선언한 UserModel 모델입니다.

from first_app.serializers import UserSerializerserializers.py에서 선언한 UserSerializer 직렬화 클래스입니다.

serializers.py는 아직 선언하지 않았으며, 다음 강좌에서 자세히 다룹니다.



ModelViewSet


# Create your views here.
class UserViewSet(viewsets.ModelViewSet):
    queryset = UserModel.objects.all()
    serializer_class = UserSerializer
    
    def get_queryset(self):
        return UserModel.objects.all()

UserViewSet의 이름으로 뷰셋 클래스를 생성하고, ModelViewSet을 상속받아 사용합니다.

ModelViewSet 클래스는 mixin 클래스를 사용하며, create(), update(), list() 등의 읽기/쓰기 기능을 모두 제공합니다.

ModelViewSet 클래스를 사용하게 되면, querysetserializer_class를 사용해야 합니다.

queryset은 테이블의 모든 데이터를 가져오게 하며, serializer_class는 추후에 선언할 UserSerializer를 연결합니다.

get_queryset 메서드는 queryset을 선언하지 않았을 때 사용합니다.

현재 코드에서는 필수요소는 아니지만, 예제를 위해 사용합니다.

get_queryset을 선언했을 때, 동일하게 테이블의 모든 데이터를 가져오게합니다.



create(POST)


def create(self, request, *args, **kwargs):
    serializer = UserSerializer(data=request.data)
    if serializer.is_valid(raise_exception=False):
        serializer.save()
        return Response({"message": "Operate successfully"}, status=status.HTTP_201_CREATED)
    else:
        return Response({"message": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)

create() 메서드는 POST와 관련된 메서드로 볼 수 있습니다.

데이터베이스 테이블의 쓰기 기능을 의미합니다.

serializer요청 데이터(request.data)를 입력해 데이터를 직렬화 시킬 수 있도록 전달합니다.

그 후, serializer.is_valid(raise_exception=False)를 통해 직렬화된 데이터의 유효성을 검사합니다.

raise_exception=False을 통해, 오류를 발생시키지 않습니다.

오류를 발생시키지 않는 이유는 Response를 통해 별도의 포맷으로 제공하기 위함입니다.

유효성 검사에 통과한다면 참(True) 값을 반환하며, 통과하지 못한다면 거짓(False) 값을 반환합니다.

유효성 검사에 통과한 경우에는 serializer.save()을 통해 데이터를 데이터베이스 테이블에 저장합니다.

이 후, 각각 Response()메서드를 통해 메세지HTTP 상태 코드(status)를 반환합니다.


  • Tip : POST 메서드는 새로운 리소스를 생성(create)할 때 사용됩니다.
  • Tip : status.HTTP_201_CREATED는 요청이 성공적으로 처리되었으며, 자원이 생성되었음을 나타내는 성공 상태 응답 코드입니다.
  • Tip : HTTP_400_BAD_REQUEST는 잘못된 문법이나 제한 조건으로 인하여 서버가 요청을 이해할 수 없음을 의미하는 상태 응답 코드입니다.

list(GET)


def list(self, request):
    # queryset = UserModel.objects.all()
    # serializer = UserSerializer(queryset, many=True)
    serializer = UserSerializer(self.get_queryset(), many=True)
    return Response(serializer.data, status=status.HTTP_200_OK)

list() 메서드는 GET과 관련된 메서드로 볼 수 있습니다.

데이터베이스 테이블의 읽기 기능을 의미합니다.

주석 처리된 querysetserializer로도 데이터베이스의 테이블에서 값을 읽을 수도 있습니다.

queryset에서 테이블에서 값을 가져와, UserSerializer에 값을 제공합니다.

many=True일 경우 여러 개의 데이터를 입력할 수 있습니다.

이 후, Response()메서드를 통해 직렬화된 데이터를 전달합니다.


  • Tip : GET 메서드읽거나(Read) 검색(Retrieve)할 때에 사용되는 메서드입니다.
  • Tip : status.HTTP_200_OK는 요청이 성공했음을 나타내는 성공 응답 상태 코드입니다.



retrieve(GET)


def retrieve(self, request, uuid=None):
    try:
        objects = UserModel.objects.get(id=uuid)
        serializer = UserSerializer(objects)
        return Response(serializer.data, status=status.HTTP_200_OK)
    except ObjectDoesNotExist:
        return Response({"message": "존재하지 않는 UUID({})".format(uuid)}, status=status.HTTP_404_NOT_FOUND)

retrieve() 메서드는 GET과 관련된 메서드로 볼 수 있습니다.

데이터베이스 테이블의 읽기(검색) 기능을 의미합니다.

uuid 매개변수는 urls.py에서 입력된 변수명을 의미합니다. serializers.py와 마찬가지로 아직 작성하지 않았습니다.

try 구문 안의 코드로도 읽기 기능을 작성할 수 있지만, 올바르지 않은 값을 검색했을 때 예외 처리를 위해 except를 추가합니다.

UserModel.objects.get(id=uuid)UserModel객체(objects)에서 하나의 열(Row)을 가져오기 위해 get() 메서드를 사용합니다.

가져올 키 값을 id로 설정하고, 입력받은 uuid를 대입합니다.

그럴 경우, id 필드에서 uuid와 일치하는 열이 objects 변수에 저장됩니다.

성공적으로 값을 불러왔을 때, serializer.data200 OK로 응답합니다.

검색한 id의 값이 존재하지 않는 경우 ObjectDoesNotExist 오류가 발생하므로, except 구문에서 오류 메세지를 반환합니다.


  • Tip : retrieve() 메서드의 uuid 매개변수는 urls.py의 설정에 따라 달라질 수 있습니다.
  • Tip : UserModel.objects.get(id=uuid)idmodels.pyUserModel에서 선언한 id = models.UUIDField()id 필드(변수)를 의미합니다.



update(PUT)


def update(self, request, uuid=None):
    objects = UserModel.objects.get(id=uuid)
    serializer = UserSerializer(objects, data=request.data)
    if serializer.is_valid(raise_exception=False):
        serializer.save()
        return Response({"message": "Operate successfully"}, status=status.HTTP_200_OK)
    else:
        return Response({"message": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)

update() 메서드는 PUT과 관련된 메서드로 볼 수 있습니다.

데이터베이스 테이블에 수정 기능을 의미합니다.

검색 기능과 마찬가지로 특정 uuid를 통해 검색된 열(Rows)의 값을 수정합니다.

수정할 열의 데이터를 검색 기능처럼 가져오며, 쓰기 기능처럼 요청 받은 값을 전달합니다.

차이점은 새로 생성하는 것이 아니므로, 검색된 열(objects)과 요청 받은 값(request.data)UserSerializer에 같이 전달합니다.

이후, 쓰기 기능처럼 유효성을 검사하고 결과에 맞게 응답합니다.


  • Tip : update() 메서드의 uuid 매개변수는 urls.py의 설정에 따라 달라질 수 있습니다.



destroy(DELETE)


def destroy(self, request, uuid=None):
    objects = UserModel.objects.get(id=uuid)
    objects.delete()
    return Response(status=status.HTTP_204_NO_CONTENT)

destroy() 메서드는 DELETE과 관련된 메서드로 볼 수 있습니다.

데이터베이스 테이블의 삭제 기능을 의미합니다.

동일하게 삭제할 id를 검색하고, delete() 메서드로 열을 지웁니다.

삭제 처리가 완료됐다면, 응답 상태를 반환합니다.


  • Tip : destroy() 메서드의 uuid 매개변수는 urls.py의 설정에 따라 달라질 수 있습니다.
  • Tip : status.HTTP_204_NO_CONTENT는 요청이 성공했으나 클라이언트가 현재 페이지에서 벗어나지 않아도 된다는 것을 의미하는 상태 응답 코드입니다.



상속하지 않고 사용하기


# def list(self, request):
#     # queryset = UserModel.objects.all()
#     # serializer = UserSerializer(queryset, many=True)
#     serializer = UserSerializer(self.get_queryset(), many=True)
#     return Response(serializer.data, status=status.HTTP_200_OK)

현재 클래스에서 선언된 create(), list() 메서드 등은 mixins 클래스에서 상속된 메서드입니다.

그러므로, 선언하지 않아도 기본적으로 선언된 메서드들을 사용할 수 있습니다.

만약, list() 메서드를 일괄 주석처리하더라도 ListModelMixin가 적용됩니다.

ListModelMixin 클래스는 UserViewSet 아래에 선언한 queryset 또는 get_queryset을 불러와 사용합니다.

그러므로, queryset 또는 get_queryset을 선언해야합니다.


도움이 되셨다면 광고 클릭 부탁드립니다.


Book Image

책이 출간되었습니다!

C#과 파이썬을 활용한 OpenCV 4 프로그래밍

컴퓨터 비전 기초 이론부터 머신러닝을 활용한 영상 처리 프로젝트까지

  • C# OpenCvSharp4
  • Python OpenCV4
  • Using Tesseract
  • Using TensorFlow
  • Using Regular Expression
  • 윤대희 저 | 위키북스

    [yes24 바로가기] [알라딘 바로가기] [교보문고 바로가기]


    ⤧  Previous post Python Django 강좌 : 제 5강 - Model ⤧  Next post Python Django 강좌 : 제 7강 - Serializers
    Python-Django Category