Serialization, Requests & Responses, Class-based views
2017-09-04
Django REST framework๋ ๋ค์ํ ์ฑ์์ DB์ ์ ๊ทผํ ์ ์๋ API endpoint๋ฅผ ๋ง๋ค์ด์ฃผ๋ ํ๋ ์์ํฌ์ ๋๋ค. Django REST framework Tutorial์ ๋ฐ๋ผํ๋ฉฐ ๊ณต๋ถํ ๋ด์ฉ์ ์ ๋ฆฌํ์ต๋๋ค.
๐ Django REST framework (2) - Authentication & Permissions, Relationships & Hyperlinked API
Serializing ์ ๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ Python ๋ค์ดํฐ๋ธ ๋ฐ์ดํฐ ํ์ ์ผ๋ก, ๊ทธ๊ฒ์ ๋ค์ JSON์ผ๋ก ๋ณํํ๋ ๊ฒ์ ๋งํ๋ค.
ํ์ด์ฌ ์ฝ๋๋ก ์ ๊ทผํ๋ ๋ฐ์ดํฐ๋ฅผ JSON์ผ๋ก ๋ณํํด์ฃผ๋ ๊ฒ์ด ๋ฐ๋ก ์ด Serializer.py
์ ์ญํ ์ด๋ค. (์ ๊ทผ ๊ฐ๋ฅํ API endpoint ๋ฅผ ๋ง๋ ๋ค๋ ๊ฒ์ ๋ฐ์ดํฐ ํ์
์ ์ ๊ทผ ๊ฐ๋ฅํ๋๋ก ๋ง๋ ๋ค๋ ์๋ฏธ๋ ํฌํจํ๋ ๊ฒ ์๋๊น...)
Serializer ํด๋์ค๋ ์ฅ๊ณ ์ ํผ ํด๋์ค์ ๋งค์ฐ ๋น์ทํ๋ค. ํ๋์ required
, max_length
, default
๊ฐ์ ํ๋๊ทธ๋ ๋๊ฐ์ด ์ฌ์ฉํ๋ค.
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()
serializer = SnippetSerializer(snippet)
serializer.data
# {'id': 2, 'title': u'', 'code': u'print "hello, world"\n', 'linenos': False, 'language': u'python', 'style': u'friendly'}
content = JSONRenderer().render(serializer.data)
content
# '{"id": 2, "title": "", "code": "print \\"hello, world\\"\\n", "linenos": false, "language": "python", "style": "friendly"}'
Deserializing ์ ๊ทธ ๋ฐ๋์ ํ๋ก์ธ์ค(JSON์์ Python native data๋ก)๋ฅผ ์๋ฏธํ๋ค.
from django.utils.six import BytesIO
stream = BytesIO(content)
data = JSONParser().parse(stream)
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>
request.data
๋ ์ผ๋ฐ์ ์ธ HttpRequest
๋ณด๋ค ๋ ์ ์ฐ(flexible request parsing)ํ๋ค.request.POST # ํผ ๋ฐ์ดํฐ๋ง ๋ค๋ฃธ. POST ๋ฉ์๋๋ง ๊ฐ๋ฅ.
request.data # ์์ ๋ฐ์ดํฐ ๋ค๋ฃธ. POST, PUT, PATCH ๊ฐ๋ฅ.
return Response(data) # ํด๋ผ์ด์ธํธ์์ ์์ฒญ๋ ํ์
์ผ๋ก ๋ ๋๋ง ํ๋ค.
status
๋ชจ๋์์๋ HTTP_400_BAD_REQUEST
์ ๊ฐ์ด ๋ช
์์ ์ธ status code๋ฅผ ์ ๊ณตํ๋ค. ์ธ์๋ฆฌ ์ซ์๋ง ์ฌ์ฉํ๋ status code ๋ณด๋ค ๋ ์ดํดํ๊ธฐ ์ฝ๋ค.@api_view
์ฅ์์๋ฅผ, CBV์์๋ APIView
ํด๋์ค๋ฅผ ์ฌ์ฉํด์ API view๋ฅผ ๋ํํ์ฌ ์ฌ์ฉํ๋ค. Request, response, status, error ์ ๊ด๋ จ๋ ๊ธฐ๋ฅ์ด ์๋ํ ์ ์๋๋ก ํด์ค๋ค.from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework import mixins
from rest_framework import generics
class SnippetList(mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
# The base class provides the core functionality, and the mixin classes provide the .list() and .create() actions. We're then explicitly binding the get and post methods to the appropriate actions.
def get(self, request, *args, **kwargs):
# `*args`, `**kwargs` ์๋ snippet์ id๋ title๊ฐ์ ํ๋ผ๋ฏธํฐ๊ฐ ๋ค์ด๊ฐ๋ค.
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
์ฌ๊ธฐ์ ListModelMixin
, CreateModelMixin
๋ฑ์ ํ๋ฒ ๋ ๋ํํ generics class๋ฅผ ์ฐ๋ฉด ์๋์ฒ๋ผ ๋ ์งง์์ง๋ค.
** Github์์ ์์ค์ฝ๋ ๋ณด๊ธฐ - mixins.py, generics.py
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework import generics
class SnippetList(generics.ListCreateAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
To be continued!