본문 바로가기

dev course - DE/TIL

[데브코스] TIL 13일차

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