Django - rest framework

문주은·2022년 6월 30일
0

1. rest framework 사용해야 하는 이유

  • 정형화된 중복을 줄일 수 있도록 도와주는 Class Based View 등 다양한 기능 지원

🖥 rest framework 표준

# ==== models.py ====
from django.db import models

class Patient(models.Model):
	pid = models.CharField(max_length=100, default="")
    pname = models.CharField(max_length=100, default="")
    created_date = models.DateField(default=timezone.now)
    
    
# ==== serializer.py ====
from rest_framework.serializers import ModelSerializer
from .models import Patient

class PatientSerializer(serializers.ModelSerializer):
    class Meta:
        model = Patient
        fields = "__all__"
        
        
# ==== views.py ====
from rest_framework.viewsets import ModelViewSet
from .serializers import PatientSerializer
from .models import Post

class PatientViewSet(ModelViewSet):
	queryset = Patient.object.all()
    serializer_class = PatientSerializer
    
    
# ==== urls.py ==== 
from rest_framework.routers import DefaultRouter
from . import views

router = DefaultFrouter()
router.register('patients', views.PatientsViewSet)
print(router.urls) # url pattern list 

urlpatterns = [
	path('', include(router.urls))
]

[rest framework를 사용하기 전]

  • views.py에서 각 함수마다 request.method가 (POST/GET/그 외) 최대 3개로 분기되는 코드 작성

[rest framework를 사용 후]

  • 함수마다 request.method에 따른 분기된 코드를 사용하지 않고 한번에 제공
    (PatientViewSet에서 queryset, serializer_class를 통해 분기 되지 않은 코드를 router에 등록해서 사용 가능)

2. Serializer

  • Form과 유사한 방식으로 동작

🖥 기본적인 serializer 사용법

# ==== serializer.py ====
from rest_framework import serializers
from .models import Patient

class PatientSerializer(serializers.ModelSerializer):
    class Meta:
        model = Patient
        fields = "__all__"
        
        
# ==== views.py ====
from .serializers import PatientSerializer
from django.http import JsonResponse
from rest_framework.renderers import JSONRenderer
from rest_framework.viewsets import ModelViewSet

"""
실제 활용을 위한 아래의 코드 Description:
  1) PatientViewSet ->  create Patient
  2) PatientListAPIView -> Load Patient List 
"""

# 임시) 첫번째 patient 정보를 serializer를 통해 조회
first_patient = Patient.objects.first()
serializer = PatientSerializer(data=first_patient)

# 임시) 모든 patient 정보를 serializer를 통해 조회
all_patient = Patient.objects.all()
serializer = PatientSerializer(data=all_patient, many=True)

class PatientViewSet(ModelViewSet):
	queryset = Patient.object.all()
    serializer_class = PatientSerializer
    
class PatientListAPIView(generics.ListCreateAPIView):
	queryset = Patient.objects.all()
    serializer_class = PatientSerializer


# ==== urls.py ====
urlpatterns = [
	path('patientlist/', views.PatientListAPIView.as_view()),
	path('', include(router.urls))
]
  • 모델에 대한 다수의 정보(queryset 객체)를 serializer로 넘길 때는 'many=True'라는 파라미터 사용
  • 모델에 대한 하나의 정보(Model 객체)를 serializer로 넘길 때는 'many=False'라는 파라미터 사용
  • ModelViewSet을 통해 patient 모델 정보 GET(목록), POST(생성)
  • generics.ListCreateAPIView를 통해 patient queryset 목록을 읽을 수 있음

🖥 Serializer를 사용한 유효성 검증

  • DRF를 사용한 유효성 검증은 APIView를 사용
  • 아래의 코드는 serializer만을 사용한 유효성 검증
# ==== views.py ====
if serializer.is_valid():
	return JsonResponse(serializer.data, status=201) # success
return JsonResponse(serializer.errors, status=400)

3. 직렬화 방법들

🖥 방법1) 직접 변환 JSON Encoder

# ==== views.py ====
from django.core.serializers.json import DjangoJSONEncoder

data = [
	{'pid': patient.pid, 
    'pname': patient.pname, 
    'created_date': patient.created_date}
    for patient in Patient.objects.all()
]

json.dumps(data, cls=DjangoJSONEncoder, ensure_ascii=False)

🖥 방법2) JSONRenderer 사용

  • json.dumps에 대한 래핑 클래스로 편리한 직렬화를 지원
# ==== views.py ====
FROM rest_framework.renderers import JSONRenderer
json_utf8_string = JSONRenderer().render(serializer.data)

🖥 방법3) DjangoJSONEncoder 사용

# ==== views.py ====
from django.core.serializers.json import DjangoJSONEncoder
from django.db.models.query import QuerySet

class MyJsonEncoder(DjangoJSONEncoder):
    def default(self, obj):
        if isinstance(obj, QuerySet):
            return tuple(obj)
        elif isinstance(obj, Patient):
            return {'pid': obj.pid, 'pname': obj.pname, 'created_date': obj.created_date}
        elif hasattr(obj, 'as_dict'):
        	return obj.as_dict()
        return super().default(obj)
        
data = Patient.object.all()
json.dumps(data, cls=MyJsonEncoder, ensure_ascii=False)
profile
Data Engineer

0개의 댓글