weekly learning2019. 6. 29. 19:49

Django Rest Framework 사용하기


먼저 Django Rest Framework를 설치한다.

pip install djangorestframework


설치 했으니 INSTALLED_APPS에 추가한다.

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
]


앱과 모델을 간단하게 만들어보자.

from django.db import models
from django.contrib.auth import get_user_model

class Tweet(models.Model):
    author = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, related_name='tweets')
    text = models.TextField()
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)


API 뷰를 동작하게 하려면 Serializer와 View 두 가지가 필요하다.

먼저 앱의 디렉토리에 serializers.py 파일을 만든다.

tweet 앱에 serializers.py를 생성했다.


serializers.py

class TweetSerializer(serializers.ModelSerializer):
    class Meta:
        model = Tweet
        fields = '__all__'


기본 뷰를 작성한다. API 뷰도 함수형, 클래스형 뷰를 만들 수 있다.

from rest_framework import generics
from .serializers import TweetSerializer
from .models import Tweet

class TweetView(generics.ListCreateAPIView):
    queryset = Tweet.objects.all()
    serializer_class = TweetSerializer


뷰를 urls.py에 추가한다.

from django.urls import path
from .views import TweetView

urlpatterns = [
    path('', TweetView.as_view()),
]


config/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('tweet.urls')),
]


브라우저를 통해 뷰가 동작하는지 확인한다.


목록 뷰를 추가했으니 수정, 삭제를 위한 뷰를 추가한다.

class TweetDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Tweet.objects.all()
    serializer_class = TweetSerializer


urls.py에 뷰를 추가한다.

from django.urls import path
from .views import TweetView, TweetDetail

urlpatterns = [
    # ...
    path('detail/<int:pk>/', TweetDetail.as_view()),
]


마찬가지로 브라우저를 통해 동작을 확인한다.

url : http://127.0.0.1:8000/detail/1/


지금까지는 일반 API 뷰 렌더링 페이지가 아닌, 개발 편의를 위해 제공되는 BrowsableAPIRenderer 페이지이다.


나오는 형식을 제한 하기 위해서는 주소에 형식을 기입하거나 뷰에서 설정해야 한다.


url에 http://127.0.0.1:8000/?format=json 와 같이 주소에 format 인자를 추가해 결정


또는


뷰에 renderer_class를 명시하여 지정

from rest_framework.renderers import JSONRenderer
class TweetDetail(generics.RetrieveUpdateDestroyAPIView):
    # ...
    renderer_classes = [JSONRenderer]



이제 API 문서를 위한 Swagger를 설치하여 사용해보자.

pip install django-rest-swagger==2.1.2


INSTALLED_APPS에 추가해준다.

INSTALLED_APPS = [
    # ...
    'rest_framework_swagger',
]


config/urls.py에 swagger 뷰를 추가한다.

from rest_framework_swagger.views import get_swagger_view

schema_view = get_swagger_view(title='Tweet API')

urlpatterns = [
    # ...
    path('api/doc/', schema_view),
]


브라우저를 통해 페이지에 접속해 본다. Swagger가 자동으로 API 문서 뷰를 생성해 주기 때문에 편리하게 사용할 수 있다.



이제 인증 과정을 추가하자. API를 만들 때 가장 많이 사용하는 방식이 토큰 방식이다.


INSTALLED_APPS에 아래를 추가한다.

INSTALLED_APPS = [
    # ...
    'rest_framework.authtoken',
]


토큰 기능을 추가하면 데이터베이스에 추가 테이블이 필요하다. migrate 명령을 실행한다.

python manage.py migrate


토큰 앱을 추가하면 토큰을 자동 생성하는 기능 역시 추가되어 있다.


토큰을 발급받는 뷰만 추가해주면 토큰을 받아서 확인할 수 있다.


config/urls.py에 뷰를 추가한다.

from rest_framework.authtoken.views import obtain_auth_token

urlpatterns = [
    # ...
    path('api/get_token/', obtain_auth_token),
]


이제 Swagger 페이지에 접속해서 토큰을 발급받아 보자.


data의 계정명과 비밀번호를 "string" 대신에 입력한다.


Try it out! 을 누르면 다음 처럼 토큰을 발급받을 수 있다.


인증 기능을 추가했다면 모든 API뷰가 로그인 해야만 동작할 수 있도록 추가할 수 있다.


config/settings.py에 관련 설정을 추가한다.

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
}


이제 모든 뷰는 토큰 인증 등 로그인 사용자만 사용할 수 있는 상태가 되었다. 하지만 회원 가입 등의 뷰는 인증 없이도 동작해야 한다.


만약 인증없이 사용해야 하는 뷰가 존재 한다면 다음과 같이 추가한다.

from rest_framework.permissions import AllowAny

class SomeView(SomeGenericView):
    permission_classes = (AllowAny,)


인증 기능을 이용하려면 POST맨 등에서 토큰을 전달해 접속해야 한다.


하지만 테스트를 할 때는 불편하므로 Swagger에 Token 인증 방법을 추가하고 사용할 수 있도록 해보자.


settings.py에 기본 인증 설정을 추가한다.

REST_FRAMEWORK = {
    # ...
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    ),
}

SWAGGER_SETTINGS = {
    'SECURITY_DEFINITIONS': {
        "api_key": {
            "type":"apiKey",
            "name":"Authorization",
            "in":"header",
        }
    }
}


다음 주 부터 다른 스쿨 분들과 협업을 하는 시간이 주어지는데 이 API를 유용하게 사용할 수 있다.


아직 사용법에 있어서 크게 와 닿지는 않지만 직접 다른 분들과 협업을 하면서 이것 저것 건들다 보면 감이 올 것이라고 생각한다.



Posted by gawain