Serilaizer
- Serialize
- 모델 인스턴스*나 QuerySet*과 같은 데이터를 JSON 형식의 파일로 변환하는 작업
- Deseialize
- JSON 형식의 데이터를 정의된 포맷에 맞춰 다시 모델 인스턴스*로 변환하는 작업
*인스턴스 : 일반적으로 실행 중인 임의의 프로세스, 클래스의 현재 생성된 오브젝트를 가리킴(출처 : 위키피디아)
*QuerySet : 데이터베이스에서의 데이터 컬렉션
주어진 JSON 값을 Serialize로 저장하기
- polls_api/serializers.py
from rest_framework import serializers
from polls.models import Question
class QuestionSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
question_text = serializers.CharField(max_length=200)
pub_date = serializers.DateTimeField(read_only=True)
def create(self, validated_data):
return Question.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.question_text = validated_data.get('question_text', instance.question_text)
instance.save()
return instance
- shell에서 사용
## Serialize
>>> from polls.models import Question
>>> from polls_api.serializers import QuestionSerializer
>>> q = Question.objects.first()
>>> serializer = QuestionSerializer(q)
>>> serializer.data
>>> from rest_framwork.renders import JSONRenderer
>>> json_str = JSONRenderer().render(serializer.data)
>>> json_str
## Deserialize
>>> import json
>>> data = json.loads(json_str)
# Create
>>> serializer = QuestionSerializer(data=data)
>>> serializer.is_vaild()
>>> serializer.validated_data
>>> new_question = serializer.save()
# Update
>>> data={'question_text':'제목수정'}
>>> serializer = QuestionSerializer(new_question, data=data)
>>> serializer.is_valid()
>>> serializer.save()
## Validation이 통과하지 않는 경우
>>> long_text = "aVDFSf"*300
>>> data = {'question_text':long_text}
>>> serializer = QuestionSerializer(data=data)
>>> serializer.is_valid()
>>> serializer.errors
ModelSerializer
앞서 직접 적었던 serializer.Serializer 보다 훨씬 간편하게 구현 가능
- polls_api/serializers.py
from rest_framework import serializers
from polls.models import Question
class QuestionSerializer(serializers.ModelSerializer):
class Meta:
model = Question
fields = ['id','question_text', 'pub_date']
- shell에서 사용
>>> from polls_api.serializers import QuestionSerializer
>>> print(QuestionSerializer())
>>> serializer = QuestionSeiralizer(data={'question_text':'모델 시리얼라이저로 만들어보기'})
>>> serializer.is_valid()
>>> serializer.save()
HTTP methods
요청 메서드를 정의해, 주어진 리소스에 수행하길 원하는 행동을 나타냄
- Create : POST
- Read : GET
- Update : PUT
- Delete : DELETE
method 기반으로 API 기능 구현
API 기능 구현 - GET
Question에 대해 JSON 형식으로 데이터를 제공하는 기능을 구현해보자
- polls_api/views.py
from polls.models import Question
from polls_api.serializers import QuestionSerializer
from rest_framework.response import Response
from rest_framework.decorators import api_view
@api_view()
def question_list(request):
questions = Question.objects.all()
serializer = QuestionSerializer(questions, many = True)
return Response(serializer.data)
- polls_api/urls.py
from django.urls import path
from .views import *
urlpatterns = [
path('question/', question_list, name='question-list')
]
- mysite/urls.py
from django.urls import include, path
from django.contrib import admin
urlpatterns = [
path('admin/', admin.site.urls),
path('polls/', include('polls.urls')),
path('rest/', include('polls_api.urls')),
]
API 기능 구현 - POST
- polls_api/views.py
from rest_framework.decorators import api_view
from polls.models import Question
from polls_api.serializers import QuestionSerializer
from rest_framework.response import Response
from rest_framework import status
@api_view(['GET','POST'])
def question_list(request):
if request.method == 'GET':
questions = Question.objects.all()
serializer = QuestionSerializer(questions, many = True)
return Response(serializer.data)
if request.method == 'POST':
serializer = QuestionSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
API 기능 구현 - PUT/DELETE
- views.py
from django.shortcuts import get_object_or_404
@api_view(['GET','PUT','DELETE'])
def question_detail(request, id):
question = get_object_or_404(Question, pk=id)
if request.method == 'GET':
serializer = QuestionSerializer(question)
return Response(serializer.data)
if request.method == 'PUT':
serializer = QuestionSerializer(question, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
if request.method == 'DELETE':
question.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
- polls_api/urls.py
from django.urls import path
from .views import *
urlpatterns = [
path('question/', question_list, name='question-list'),
path('question/<int:id>/', question_detail, name='question-detail')
]
class 기반으로 API 기능 구현 - 상속을 받을 수 있기 때문에 다시 작성할 필요 없이 상속 가능
- polls_api/views.py
from rest_framework.views import APIView
# 클래스로 구현
class QuestionList(APIView):
def get(self, request):
questions = Question.objects.all()
serializer = QuestionSerializer(questions, many=True)
return Response(serializer.data)
def post(self, request):
serializer = QuestionSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class QuestionDetail(APIView):
def get(self, request, id):
question = get_object_or_404(Question, pk=id)
serializer = QuestionSerializer(question)
return Response(serializer.data)
def put(self, request, id):
question = get_object_or_404(Question, pk=id)
serializer = QuestionSerializer(question, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, id):
question = get_object_or_404(Question, pk=id)
question.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
- polls_api/urls.py
from django.urls import path
from .views import *
# as_view() : get인지 post인지 알아서 걸러줌. if문이라고 생각하면 됨
urlpatterns = [
# path('question/', question_list, name='question-list'), # 메서드로 구현
path('question/', QuestionList.as_view(), name='question-list'),
# path('question/<int:id>/', question_detail, name='question-detail') # 메서드로 구현
path('question/<int:id>/',QuestionDetail.as_view(), name='question-detail'),
]
mixins 활용해 간단하게 기능 구현
- polls_api/views.py
from polls.models import Question
from polls_api.serializer import QuestionSerializer
from rest_framework import mixins, generics
class QuestionList(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView):
queryset = Question.objects.all()
serializer_class = QuestionSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
class QuestionDetailmixins(mixins.ListModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, generics.GenericAPIView):
queryset = Question.objects.all()
serializer_class = QuestionSerializer
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
- polls_api/urls.py
from django.urls import path
from .views import *
urlpatterns = [
path('question/', QuestionList.as_view(), name='question-list'),
path('question/<int:pk>/', QuestionDetail.as_view(), name='question-detail'),
] # generic은 pk로 가져옴
generic 활용해 더 간단하게 기능 구현
- polls_api/views.py
from polls.models import Question
from polls_api.serializers import QuestionSerializer
from rest_framework import generics
class QuestionList(generics.ListCreateAPIView):
queryset = Question.objects.all()
serializer_class = QuestionSerializer
# generics.ListCreateAPIView로 아래 코드 자동 상속
# def get(self, request, *args, **kwargs):
# return self.list(request, *args, **kwargs)
# def post(self, request, *args, **kwargs):
# return self.create(request, *args, **kwargs)
class QuestionDetailmixins(generics.RetrieveUpdateDestroyAPIView):
queryset = Question.objects.all()
serializer_class = QuestionSerializer
# generics.RetrieveUpdateDestroyAPIView로 아래 코드 자동 상속
# def get(self, request, *args, **kwargs):
# return self.retrieve(request, *args, **kwargs)
# def put(self, request, *args, **kwargs):
# return self.update(request, *args, **kwargs)
# def delete(self, request, *args, **kwargs):
# return self.destroy(request, *args, **kwargs)
'dev course - DE > TIL' 카테고리의 다른 글
[데브코스] TIL 15일차 (0) | 2024.04.16 |
---|---|
[데브코스] TIL 14일차 (0) | 2024.04.13 |
[데브코스] TIL 12일차 (0) | 2024.04.09 |
[데브코스] TIL 11일차 (0) | 2024.04.08 |
[데브코스] TIL 10일차 (0) | 2024.04.05 |