encode/rest-framework-tutorial 에서 코드를 확인 할 수 있습니다
pip install django
pip install djangorestframework
pip install pygments # We'll be using this for the code highlighting
먼저 가상환경으로 진입 후에 위의 코드들을 install 해줍니다
그리고 앞선 맛보기의 tutorial의 project를 활용해서 프로젝트를 진행해 보겠습니다.
앱의 경우 snippets로 시작하겠습니다
python manage.py startapp snippets
등록 후에 해야할 작업이 있죠?
#apps
'rest_framework',
#local apps
'snippets',
INSTALLED_APPS에 꼭 추가해줍니다
그 뒤 snippets/models.py에 가서 model을 작성합니다
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']
paygments같은 경우 code를 highlight 하기 위해서 작성하는 것 같습니다.
그 뒤 마이그레이션을 생성하고 데이터베이스를 동기화 합니다
python manage.py makemigrations snippets
python manage.py migrate snippets
튜토리얼 1번의 제목이자 DRF에서 가장 중요한 기능인 Serializer를 진행해 봅니다.
웹 API를 위해 가장 먼저 데이터를 json형식으로 보내주어야합니다.
그를 위해서 serializers.py에 다음 코드를 추가합니다.
from rest_framework import serializers
from snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES
class SnippetSerializer(serializers.Serializer):
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
serializer 클래스의 첫 부분은 직렬화/역직렬화 되는 필드를 정의합니다. create()와 update()는 호출 시 완전한 기능을 갖춘 인스턴스가 생성되거나 수정되는 방법을 정의해 둡니다.
가만히 보면 앞서 작성한 Django model과 유사한 점이 많습니다. 예를 들면 required나 max_length 그리고 default와 같은 기능들이 말이죠
HTML 랜더링 할때 특정 상황에서 serializer이 표시되는 방법도 바꿀 수 있습니다. 이러한 점은 나중에 알아보도록 하겠습니다.
이제 django shell을 이용해서 Serializer 클래스가 어떠한 작업을 하는 지 알아보도록 하겠습니다
python manage.py shell
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
snippet = Snippet(code='foo = "bar"\n')
snippet.save()
snippet = Snippet(code='print("hello, world")\n')
snippet.save()
앞서 작성한 Snippet에 값을 넣고
serializer = SnippetSerializer(snippet)
serializer.data
# {'id': 2, 'title': '', 'code': 'print("hello, world")\n', 'linenos': False, 'language': 'python', 'style': 'friendly'}
Serializer을 작성하게 되면
작성한 코드가 json형태로 나오고
content = JSONRenderer().render(serializer.data)
content
# b'{"id": 2, "title": "", "code": "print(\\"hello, world\\")\\n", "linenos": false, "language": "python", "style": "friendly"}'
python의 형태로도 나오는 것을 볼 수 있습니다
역직렬화의 경우도 비슷합니다
import io
stream = io.BytesIO(content)
#<_io.BytesIO object at 0x000001B3B1BCAD40>
data = JSONParser().parse(stream)
#{'id': 2, 'title': '', 'code': 'print("hello, world")\n', 'linenos': False, 'language': 'python', 'style': 'friendly'}
content를 Bytes화 해서 JSONParser()에 넣어줍니다
serializer = SnippetSerializer(data=data)
serializer.is_valid()
# True
serializer.validated_data
# OrderedDict([('title', ''), ('code', 'print("hello, world")\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])
serializer.save()
# <Snippet: Snippet object>
is_valid()를 통해 데이터 유효성 검사를 한 뒤 통과한 후에 사용 할 수 있는 메서드로
if serializer.is_valid():
# 이 시점에서 validated_data 사용 가능
validated_data = serializer.validated_data
print(validated_data)
이렇게 사용 가능합니다
만약 여러개의 데이터를 보고 싶다면 many=True만 하게 되면 여러개의 데이터를 볼 수 있습니다
serializer = SnippetSerializer(Snippet.objects.all(), many=True)
serializer.data
# [OrderedDict([('id', 1), ('title', ''), ('code', 'foo = "bar"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('id', 2), ('title', ''), ('code', 'print("hello, world")\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('id', 3), ('title', ''), ('code', 'print("hello, world")'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])]
사실 앞선 것보다 훨씬 간결하고 빠르게 개발하는 방법이 있습니다
ModelSerializer을 사용하는 것인데요
class SnippetSerializer(serializers.ModelSerializer):
class Meta:
model = Snippet
fields = ['id', 'title', 'code', 'linenos', 'language', 'style']
이렇게 되면 앞선 것과 똑같이 model에 있는 필드를 이용해서 serializer을 진행하게 됩니다
그 뒤 이 새로운 Serializer 클래스를 이용해서 View를 작성해보겠습니다
snippets/views.py에 들어가서
@csrf_exempt
def snippet_list(request):
"""
List all code snippets, or create a new snippet.
"""
if request.method == 'GET':
snippets = Snippet.objects.all()
serializer = SnippetSerializer(snippets, many=True)
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)
위와 같이 작성하고 POST를 수행하기 위해 csrf_exempt를 작성합니다.
아래 detail을 위한 view도 작성합니다
@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)
그 뒤 view를 연결하기 위해 snipptets/urs.py l파일을 생성 후
from django.urls import path
from snippets import views
urlpatterns = [
path('snippets/', views.snippet_list),
path('snippets/<int:pk>/', views.snippet_detail),
]
기존 tutorial/urls.py 에도 연결해줍니다
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('', include('snippets.urls')),
path('admin/', admin.site.urls),
]
위와 같이 snippets/ 링크로 접속 시 list된 결과를 얻을 수 있습니다.
이렇게 DRF의 가장 중요한 serializer에 대해서 배웠고 기타 다른 기능들에 대해 전반적으로 훑어보는 시간을 가졌습니다
tutorial2에는 Requests 와 Responses에 대해 배워보겠습니다
'Django > restframework' 카테고리의 다른 글
DRF docs API Guide Responses (0) | 2024.01.12 |
---|---|
DRF docs API Guide Request (0) | 2024.01.09 |
DRF tutorial - 3 Class-based Views (0) | 2024.01.02 |
DRF tutorial -2 requests and responses (0) | 2024.01.02 |
django-restframework란 (0) | 2023.12.28 |