DRF - Tutorial 1

Daehwi Kim·2021년 6월 30일
0

DRF

목록 보기
1/2

Intro

개발자로서 취업을 하기 위해 포폴을 작성해보고, 여러군데 지원을 해보았으나 번번히 서류탈락을 했다. (흑.. 내가 열씸히 더 노력하고 공부해야겠지?)

개인적으로 프로젝트를 더해볼까 아니면 해왔던 프로젝트를 조금 더 리팩토링을 해볼까 고민을 했는데, 일단 해왔던 프로젝트를 조금 더 RESTful API에 맞게 리팩토링하고, 성능을 최적화 해보아야겠다는 생각이들었다.

그래서 RESTful API를 손쉽게 만들 수 있는 DRF를 공식문서의 Tutorial를 보면서 공부하고자 한다.!

Reference

 

Tutorial 1 - 오늘 공부한 내용

1. DRF 설치 및 세팅

pip install djangorestframework

2. Data를 Serializer 또는 Deserializer 해보기

  • model.py
from django.db       import models
from pygments.lexers import get_all_lexers
from pygments.styles import get_all_styles

LEXERS           = [item for item in get_all_lexers() if item[1]]
LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])
STYLE_CHOICES    = sorted([(item, item) for item in get_all_styles()])


class Snippet(models.Model):
    created  = models.DateTimeField(auto_now_add=True)
    title    = models.CharField(max_length=100, blank=True, default='')
    code     = models.TextField()
    linenos  = models.BooleanField(default=False)
    language = models.CharField(choices=LANGUAGE_CHOICES, default='python', max_length=100)
    style    = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100)

    class Meta:
        ordering = ['created']

  • serializers.py
from rest_framework import serializers
from Snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES


class SnippetSerializer(serializers.ModelSerializer):
    id = serializers.IntegerField(read_only=True)
    title = serializers.CharField(required=False, allow_blank=True, max_length=100)
    code = serializers.CharField(style={'base_template': 'textarea.html'})
    linenos = serializers.BooleanField(required=False)
    language = serializers.ChoiceField(choices=LANGUAGE_CHOICES, default='python')
    style = serializers.ChoiceField(choices=STYLE_CHOICES, default='friendly')

    def create(self, validated_data):
        """
        Create and return a new `Snippet` instance, given the validated data.
        """
        return Snippet.objects.create(**validated_data)

    def update(self, instance, validated_data):
        """
        Update and return an existing `Snippet` instance, given the validated data.
        """
        instance.title = validated_data.get('title', instance.title)
        instance.code = validated_data.get('code', instance.code)
        instance.linenos = validated_data.get('linenos', instance.linenos)
        instance.language = validated_data.get('language', instance.language)
        instance.style = validated_data.get('style', instance.style)
        instance.save()
        return instance

  • DB에 저장되어져있는 DATA를 ORM으로 가져온다음 Serializer해보기
>>> from Snippets.models import Snippet
>>> from Snippets.serializers import SnippetSerializer
>>> a = Snippet.objects.get(id=1)
>>> snippet = SnippetSerializer(a)
>>> snippet.data
{'id': 1, 'title': '', 'code': 'foo = "bar"\n', 'linenos': False, 'language': 'python', 'style': 'friendly'}

3. ModelSerializer Class를 이용하여 간편하게 직렬화 시키기

  • ModelSerializer Class를 상속받고 Snippet Model를 이용하여 위에서 기본 Serializer를 만든 것보다 간편하게 만들 수 있다.
class SnippetSerializer(serializers.ModelSerializer):
    class Meta:
        model = Snippet
        fields = ['id', 'title', 'code', 'linenos', 'language', 'style']

4. Serializer를 이용한 Functional API View 구현하기

  • views.py
from django.http                  import HttpResponse, JsonResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.parsers       import JSONParser
from Snippets.models              import Snippet
from Snippets.serializers         import SnippetSerializer

@csrf_exempt
def snippet_list(request):
    """
    List all code snippets, or create a new snippet.
    """
    if request.method == 'GET':
    	# queryset 
        snippets   = Snippet.objects.all()
        # many=True : 다수의 data queryset 형태를 serializer하기 위해 설정 False면 단일 queryset으로 인식
        serializer = SnippetSerializer(snippets, many=True)
        # safe=False : 직렬화한 개체를 전달하기 위해 설정 True(Default)이면 Dict만 허용
        return JsonResponse(serializer.data, safe=False)

    elif request.method == 'POST':
        data       = JSONParser().parse(request)
        serializer = SnippetSerializer(data=data)
        # 유효성 검사
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data, status=201)
        return JsonResponse(serializer.errors, status=400)

@csrf_exempt
def snippet_detail(request, pk):
    """
    Retrieve, update or delete a code snippet.
    """
    try:
        snippet = Snippet.objects.get(pk=pk)
    except Snippet.DoesNotExist:
        return HttpResponse(status=404)

    if request.method == 'GET':
        serializer = SnippetSerializer(snippet)
        return JsonResponse(serializer.data)

    elif request.method == 'PUT':
        data = JSONParser().parse(request)
        serializer = SnippetSerializer(snippet, data=data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data)
        return JsonResponse(serializer.errors, status=400)

    elif request.method == 'DELETE':
        snippet.delete()
        return HttpResponse(status=204)

Httpie를 이용한 API 테스트

  • GET (Snippet 리스트 API)
>>> http http://127.0.0.1:8000/snippets/

HTTP/1.1 200 OK
Content-Length: 478
Content-Type: application/json
Date: Wed, 30 Jun 2021 02:59:36 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.10
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

[
    {
        "code": "foo = \"bar\"\n",
        "id": 1,
        "language": "python",
        "linenos": false,
        "style": "friendly",
        "title": ""
    },
    {
        "code": "print(\"hello, world\")\n",
        "id": 2,
        "language": "python",
        "linenos": false,
        "style": "friendly",
        "title": ""
    },
    {
        "code": "print(\"hello, world\")",
        "id": 3,
        "language": "python",
        "linenos": false,
        "style": "friendly",
        "title": ""
    },
    {
        "code": "print(\"New Code Snippet\")",
        "id": 4,
        "language": "python",
        "linenos": false,
        "style": "friendly",
        "title": ""
    }
]
  • GET(단일 Snippet 호출 API)
>>> http http://127.0.0.1:8000/snippets/4/

HTTP/1.1 200 OK
Content-Length: 122
Content-Type: application/json
Date: Wed, 30 Jun 2021 03:02:37 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.10
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "code": "print(\"New Code Snippet\")",
    "id": 4,
    "language": "python",
    "linenos": false,
    "style": "friendly",
    "title": ""
}
profile
게으른 개발자

0개의 댓글