serializer는 django form과 컨셉, 사용법이 유사하다.
django form의 생성자는 첫번째 인자로 data를 받지만 serializer의 생성자는 첫번째 인자로 instancs를 받고, 두 번째 인자로 data를 받는다.
하지만 data 인자만 지정해줄때도 있는데, 이럴 때는 아래 코드와 같이 필수적으로 keyword값을 지정해주어야 한다.
serializer = PostSerializer(post)
serializer = PostSerializer(data=request.data)
serializer = PostSerializer(post, data=reqeust.data)
serializer = PostSerializer(post, reqeust.data)
serializer = PostSerializer(reqeust.data) # 오류
data= 인자가 주어지면, 다음 순서로 처리된다.
.is_valid()가 호출이 되면
.initial_data 필드에 접근할 수 있고,
.validated_data 를 통해 유효성 검증에 통과한 값들에 대한 사전에 접근. .save()시에 사용됨.
.errors : 유효성 검사에 대한 오류 내역
.data : 유효성 검사 후에, 갱신된 인스턴스에 대한 필드값 사전
#serializer.save()
def save(self, **kwargs):
pass
save()가 호출되면, 유효성 검사를 통과한 .validated_data와 kwargs dict를 합쳐서 DB로의 저장을 시도한다. 이 때, self.instance의 유무에 따라 저장하는 방식이 다르다.
- self.instance 값이 있을 때 : update() 를 통해서 저장
- self.instance 값이 없을 때 : create() 를 통해서 저장
장고 기본 validators와 더불어 drf 에서는 유효성 여부 체크를 도와주는 validator를 제공하며, queryset 범위를 제한아여 지정 범위 내에서의 유효성, 유일성 여부를 체크할 수 있다.
* Modelserializer를 사용한다면, 유효성 검사 함수는 모델 측에 지정하는 것이 관리측에서 좋다.
1. Field 에 대한 validator
validate_{field name} 이름의 함수를 사용하며 특정 필드에 대해 검사한다.
# serializers.py
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
class PostSerializer(serializers.Serializer):
title = serializers.CharField(max_length=100)
def validate_title(self, value):
if '제목' not in value:
raise ValidationError('제목이라는 말이 들어가야 합니다.')
return value
2. object 에 대한 validator
validate 이름의 함수를 사용하며 다수 필드에 대해 검사한다.
class PostSerializer(serializers.Serializer):
title = serializers.CharField(max_length=100)
def validate(self, data):
if '제목' not in data['title']:
raise ValidationError('제목이라는 말이 들어가야 합니다.')
return data
3. DB 반영을 돕는 perform 함수
사용자의 입력과 함께 추가적인 정보(예를 들면, 사용자의 ip)를 함께 DB에 저장해야 하는 경우, perform 함수를 재정의해 커스튬해야한다.
먼저, 아래와 같이 model을 정의하고 title의 값만 사용자로부터 입력받는다.
# models.py
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=100)
ip = models.GenericIPAddressField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
# serializers.py
from rest_framework.serializers import ModelSerializer
from .models import Post
class PostSerializer(ModelSerializer):
class Meta:
model = Post
fields = ['title']
그리고 ip를 자동으로 추가하기 위해 perform_create를 커스텀한다.
# views.py
from rest_framework.viewsets import ModelViewSet
from .models import Post
from .serializers import PostSerializer
class PostViewSet(ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
def perform_create(self, serializer):
serializer.save(ip=self.request.META['REMOTE_ADDR'])
'TTL > 13주차 ~ 16주차 TIL (11.21 ~ 12.16)' 카테고리의 다른 글
2022-11-25 TIL (DRF pagination) (0) | 2022.11.29 |
---|---|
2022-11-28 TIL (프로젝트 KPT 회고록) (0) | 2022.11.29 |
2022-11-24 TIL (Web Server란? Application Server란?) (0) | 2022.11.25 |
2022-11-22 TIL (dotenv로 환경변수 관리하기) (0) | 2022.11.23 |
2022-11-21 TIL (gunicorn, nginx) (0) | 2022.11.21 |