ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 코린이의 DRF(Django REST Framework) 사용해버리기~
    💻 프로그래밍/Django 2018. 12. 31. 17:54

    안녕하세요! Jay 입니다. 정말 오랜만에 글을 쓰는 것 같아요! ㅎㅎ 

    그동안 많은 일들이 있기도 했고~ 연말이라 조금 게을러진 마음을 다시 한번 다잡고자 다시 글을 씁니다!

    새로운 것들을 배우기도 했고요ㅎㅎㅎ:D

    오늘은 DRF(Django REST Framework)를 CBV(Class-Based_view)로사용하는 방법을 알아보려고 합니다.


    ※ DRF를 사용한 API만들기


    먼저 DRF를 사용하려면 해당 라이브러리를 설치해야겠죠?

     $ pip install django-rest-framework

    DRF 패키지를 설치하고 pip list 해보시면 아래와 같이 패키지가 설치된 걸 볼 수 있습니다.


    이제 API로 사용할 App을 생성해보도록 하겠습니다.


    $ django-admin startapp movie


    movie 앱을 생성하였습니다. 이제 movie 디렉토리 하위에 urls.py 와 serializers.py 를 만들면 다음과 같이 됩니다.

    다음은 settings.py에 가서 생성한 movie app을 추가해주고 REST_FRAMWORK 기본 세팅을 추가해 줍니다.

    DRF setting에서 API를 호출할때 JSON형식으로만 보이게 아래와 같이 세팅해줍니다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    # Django REST Framework
    REST_FRAMEWORK = {
        'DEFAULT_RENDERER_CLASSES': (
            'rest_framework.renderers.JSONRenderer',
        ),
    }
     
    # Application definition
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'movie',
        'rest_framework',
    ]


    movie 앱에서 model을 만들어 줍니다. Movie 모델은 영화제목, 장르, 제작년도를 값으로 가집니다.

    1
    2
    3
    4
    5
    6
    7
    # -*- coding: utf-8 -*-
    from django.db import models
     
    class Movie(models.Model):
        title = models.CharField(max_length=30# 제목
        genre = models.CharField(max_length=15# 장르
        year = models.IntegerField()  # 제작 년도


    다음으로 model에 대한 시리얼라이저를 만들어 줍니다.

    1
    2
    3
    4
    5
    6
    7
    8
    from rest_framework import serializers
    from .models import Movie
     
    class MovieSerializer(serializers.ModelSerializer):
        class Meta:
            model = Movie # 모델 설정
            fields = ('id','title','genre','year'# 필드 설정
     


    Meta 클래스를 설정할때 feilds의 경우 이렇게 따로 설정해주거나 __all__로 해줘야 합니다. 

    이제 view 를 만들어 보겠습니다. view에는 두가지 클래스를 추가해 줄겁니다.

    하나는 movie list에 대한 view, 다른 하나는 특정 객체에 대한 view입니다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    from .models import Movie
    from django.http import Http404
    from rest_framework import status
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from .serializers import MovieSerializer
     
    class MovieList(APIView):
            """
                영화 리스트 생성
            """
        def post(self, request, format=None):
            serializer = MovieSerializer(data=request.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)
     
          """
                영화 리스트 조회
          """
        def get(self, request, format=None):
            queryset = Movie.objects.all()
            serializer = MovieSerializer(queryset, many=True)
            return Response(serializer.data)
     
    class MovieDetail(APIView) :
        def get_object(self, pk):
            try :
                return Movie.objects.get(pk=pk)
            except :
                raise Http404
     
        def get(self, request, pk):
            movie = self.get_object(pk)
            serializer = MovieSerializer(movie)
            return Response(serializer.data)
     
        def put(self, request, pk, format=None):
            movie = self.get_object(pk)
            serializer = MovieSerializer(movie, data=request.data)
            if serializer.is_valid() :
                serializer.save()
                return Response(serializer.data)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
     
        def delete(self, request, pk, format=None):
            movie = self.get_object(pk)
            movie.delete()
            return Response(status=status.HTTP_204_NO_CONTENT)
     


    이제 URL 맵핑을 해보겠습니다. 

    위 view를 두가지 생성한 것 처럼 URL도 두가지를 맵핑해야합니다. 특정 객체를 위한 view는 <int:pk>라고 정의 해줍니다. 

    <int:pk> 로 url표현이 될 줄 알았는데 url을 인식하지 못하네요ㅎㅎ 그래서 장고 정규표현식(Regex)를 참고해 아래와 같이 적었습니다.

    • ^post/ : url이(오른쪽부터) post/로 시작합니다.
    • (\d+) : 숫자(한 개 이상)가 있습니다. 이 숫자로 조회하고 싶은 게시글을 찾을 수 있어요.
    • / : /뒤에 문자가 있습니다.
    • $ : url 마지막이 /로 끝납니다.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    from django.conf.urls import url
    from . import views
     
    urlpatterns = [
        url(r'(?P<pk>[0-9]+)/', views.MovieDetail.as_view(), name='detail'),
        #url(r'<int:pk>/', views.MovieDetail.as_view()) # 정규표현식 에러
        url(r'', views.MovieList.as_view(), name='movies')
    ]
    ]]></script><p></p>
    <p style="line-height: 2;"><span style="font-size: 12pt;">다음으로 장고 프로젝트 URL에 movie 앱 url을 추가합니다.</span></p>
    <script type="syntaxhighlighter" class="brush: python"><![CDATA[
    from django.conf.urls import url, include
    from django.contrib import admin
     
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'movie/', include('movie.urls')),
    ]
     


    이제 새로운 model을 정의했으니 마이그레이션을 해줘야 합니다.

     $ ./manage.py makemigrations

     $ ./manage.py migrate

    ※ API 호출 확인해보기
    Postman으로 API호출이 제대로 되는지 확인해보도록 하겠습니다.
    GET/movies/

    저장되어 있는 데이터가 없기 때문에 빈 배열을 넘겨줍니다. 그럼 데이터를 저장한 다음 다시 호출 해보겠습니다,.

    POST/movies/

    다시 GET으로 확인해보겠습니다.

    제대로 데이터가 저장된 것을 확인할 수 있습니다.

    특정 id를 가진 movie 를 조회 해보도록 하겠습니다.

    POST/movies/{pk}


    DELETE/movies/{pk}

    3번 id의 영화를 DB에서 삭제해 보겠습니다.

    삭제 후 GET으로 확인 결과

    PUT/movies/{pk}

    마지막으로 수정을 해보겠습니다.


    2번 영화를 아쿠아 -> 아쿠아맨 으로 바꾸려고 했는데 id를 잘못썼네요 ㅎㅎ 쨌든 4번 마약왕->아쿠아맨로 수정되었습니다.

    이상으로 '코린이의 DRF 사용해버리기' 포스팅이 끝났습니다. 

    다른분들에게 조금이라도 도움이 되었으면 좋겠으며, 다음 포스팅은 API문서 자동화 관리를 할 수 있는 패키지에 대해 알아보겠습니다.

    다들 즐거운 코딩하세요~:D



    댓글

운동하는 개발자 JAY-JI