API - Django Restframework API 추가 학습

  • 이번에는 클라이언트에게 특정 데이터 요청을 수신하고 전송하기 위해 django restframework api를 작성하는 방법과, Pycharm 개발도구의 Debug를 이용하여 API 요청 데이터에 대해 상세히 확인하는 방법에 대해 알아볼 것이다.

Django Restframework API 학습

1. 코드 작성할 폴더 생성

ex) drf-yasg

  • 가상환경 설정

    1
    2
    $ virtualenv --python=python3.6 venv
    $ source venv/bin/activate
  • django 모듈 설치

    1
    $ pip install django
  • rest framework 관련 모듈 설치

    1
    $ pip install djangorestframework

2. app 폴더 생성 및 프로젝트 및 앱 생성

  • django 코드를 모두 app 폴더로 이동
  • app 폴더를 root 폴더로 지정
    • pycharm 개발도구 사용하는 경우
    • app 폴더 우측 클릭
    • ‘Mark Directory as’ 클릭
    • ‘Sources Root’ 클릭
  • 프로젝트 생성 (경로: drf-yasg > app)

    1
    $ django-admin startproject config .
  • 앱 생성 (경로: drf-yasg > app)

    1
    $ python manage.py startapp blog

3. settings 수정

  • 경로 : drf-yasg > app > config > settings.py
    1
    2
    3
    4
    5
    INSTALLED_APP = [
    ...
    'rest_framework',
    'blog',
    ]

4. blog 모델 작성

  • 경로 : drf-yasg > app > blog > models.py
    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
    from django.contrib.auth import get_user_model
    from django.db import models

    User = get_user_model()


    class Post(models.Model):
    title = models.CharField(max_length=50)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    content = models.TextField(blank=True)
    is_published = models.BooleanField(default=False)
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)

    def __str__(self):
    return self.title


    class Comment(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    content = models.CharField(max_length=100)
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)

    def __str__(self):
    return self.content[:20]

5. 변경사항 저장 및 migrate, 관리자 생성

  • 경로 : drf-yasg > app
    1
    2
    3
    $ python manage.py makemigrations
    $ python manage.py migrate
    $ python manage.py createsuperuser

6. serializers 작성

  • 경로 : drf-yasg > blog > serializers.py
    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
    from rest_framework import serializers

    from .models import Post, Comment

    POST_FIELDS = (
    'title',
    'content',
    'is_published',
    )


    class PostSerializer(serializers.ModelSerializer):
    class Meta:
    model = Post
    fields = POST_FIELDS + (
    'pk',
    'author',
    'created',
    'modified',
    )


    class PostCreateSerializer(serializers.ModelSerializer):
    class Meta:
    model = Post
    fields = POST_FIELDS


    class PostUpdateSerializer(serializers.ModelSerializer):
    class Meta:
    model = Post
    fields = POST_FIELDS


    class CommentSerializer(serializers.ModelSerializer):
    class Meta:
    model = Comment
    fields = (
    'pk',
    'content',
    'created',
    'modified',
    )

7. apis 작성

  • 경로 : drf-yasg > app > blog > apis.py
    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
    52
    53
    54
    55
    56
    57
    from rest_framework import generics, permissions
    from rest_framework.response import Response
    from rest_framework.views import APIView

    from .models import Post, Comment
    from .serializers import PostSerializer, CommentSerializer, PostCreateSerializer

    # generic api view 사용하는 경우
    class PostListCreateAPIView(generics.ListCreateAPIView):
    queryset = Post.objects.all()
    permission_classes = (
    permissions.IsAuthenticatedOrReadOnly,
    )

    def get_serializer_class(self):
    if self.request.method == 'GET':
    return PostSerializer
    elif self.request.method == 'POST':
    return PostCreateSerializer

    def perform_create(self, serializer):
    serializer.save(author=self.request.user)


    class CommentListCreateAPIView(generics.ListCreateAPIView):
    queryset = Comment.objects.all()
    serializer_class = CommentSerializer

    # generic api view 사용 없이 직접 작성하는 경우
    class PostListCreateAPIView(APIView):
    def get(self, request):
    # Post모델의 QuerySet을
    posts = Post.objects.all()
    # PostSerializer를 사용해 직렬화 (many=True옵션으로 multiple objects대응)
    serializer = PostSerializer(posts, many=True)
    # Serializer의 data를 Response객체 생성의 인수로 사용
    response = Response(serializer.data)
    # 만들어진 Response객체를 리턴
    return response

    def post(self, request):
    # 새 Post를 작성
    # author는 request.user를 사용

    # request.data에 데이터가 전달됨
    # 전달받은 데이터를 data키워드인수로 PostSerializer생성에 전달, serializer생성
    serializer = PostCreateSerializer(data=request.data)

    # serializer.is_valid() 호출로 validation점검
    if serializer.is_valid():
    # valid하다면, serializer.save()를 호출해서 ModelSerializer로 DB row생성
    # -> 이 과정에서, save()에 author를 request.user로 전달
    instance = serializer.save(author=request.user)
    return Response(PostSerializer(instance).data)
    else:
    # valid하지 않다면, Response에 serializers.errors를 전달
    return Response(serializer.errors)

8. 경로 설정

  • 경로 : drf-yasg > app > blog > urls.py
    1
    2
    3
    4
    5
    6
    7
    8
    from django.urls import path

    from . import apis

    urlpatterns = [
    path('posts/', apis.PostListCreateAPIView.as_view()),
    path('comments/', apis.CommentListCreateAPIView.as_view()),
    ]

9. 프로젝트 생성한 config 경로 설정

  • 경로 : drf-yasg > app > config > urls.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    from django.contrib import admin
    from django.urls import path, include

    urlpatterns_apis = [
    path('blog/', include('blog.urls')),
    ]
    urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include(urlpatterns_apis)),
    ]

10. Debug 설정(Pycharm 기준)

  • postman 에서 api 요청 시, 요청 정보에 어떤 데이터가 있는지 확인 위해 Debug 설정
  1. 우측 상단 ‘Add Configuration’ 클릭
    Screenshot from 2019-07-22 00-50-26

  2. 좌측 ‘+’ 버튼 > Python 클릭
    Screenshot from 2019-07-22 00-50-32

  3. Script path 항목에 해당 프로젝트 경로 > manage.py 선택
    Screenshot from 2019-07-22 00-51-43

  4. Parameter 항목에 ‘runserver’ 입력 후 확인
    Screenshot from 2019-07-22 00-52-03

  5. 특정 코드 위치에 break point 설정 후, postman에서 해당 경로로 api 요청 시, 어떤 정보로 요청했는지 확인
    Screenshot from 2019-07-22 01-00-01