일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- PYTHON
- 알고리즘 풀이
- django ORM
- 알고리즘
- 알고리즘 문제
- DRF
- HTML
- js
- MAC
- 알고리즘 연습
- 백준
- form
- c++
- AWS
- django widget
- Django
- CSS
- es6
- django rest framework
- java
- javascript
- Algorithm
- API
- Baekjoon
- 파이썬 알고리즘
- react
- 장고
- web
- 파이썬
- Git
- Today
- Total
수학과의 좌충우돌 프로그래밍
[Django] Serializer 를 통한 유효성 검사 및 저장 본문
이번 포스팅에서는 Serializer 에 대해서 자세히 알아보도록 하겠습니다.
Serializer
우선 github에서의 Serializer
코드를 살펴보겠습니다.
Serializer
는 BaseSerializer
를 상속 받고 BaseSerializer
의 생성자는 아래와 같습니다.
# rest_framework/serializers.py
class BaseSerializer(Field):
def __init__(self, instance=None, data=empty, **kwargs):
# 생략
class Serializer(BaseSeializer):
# 생략
그렇기 때문에 우리는 이를 사용할 때 post
라는 instance가 먼저 나온다면 뒤에 data 라는 keyword 를 써줄 필요가 없지만 instance 없이 data 를 파라미터로 넘기기 위헤서는 keyword 가 꼭 필요합니다. 이러한 이유로 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) # 오류
이 부분이 익숙하지 않다면 python의 함수 파라미터 부분을 다시 공부하시길 바랍니다.
data 에 파라미터가 주어지면 다음과 같은 과정을 거치게 됩니다.
- serializer.is_valid() 가 호출 되었을 시,
- serializer.initial_data 에 data 값을 넣어주고
- serializer.validated_data 에 유효성 검증을 통과한 값들을 넣어주고 serializer.save() 시 이 값들을 저장하게 된다.
- serializer.errors 에는 유효성 검사에서의 오류들이
- serializer.data 에는 유효성 검사 후 인스턴스 값이 사전으로 저장된다.
serializer.save()
serializer.save() 는 다음과 같이 **kwargs 를 받습니다.
def save(self, **kwargs):
pass
이 경우에 유효성을 통과한 validated_data
와 kwargs
dict가 합쳐져서 DB에 저장을 하게 됩니다.
이 때, self.instance가 에 따라 저장하는 방식이 다릅니다.
- self.instance 값이 있을 때 : update() 를 통해서 저장
- self.instance 값이 없을 때 : create() 를 통해서 저장
Validators
serializer
에서도 validator
를 제공해주고 있습니다.
django의 기본 validator
와 더불어 유일성을 확인해주는 것도 제공해주고 있습니다.
간단히 하나면 살펴보겠습니다.
-
UniqueValidator
- 지정 필드가 queryset 에서 Unique한지 확인을 해주게 됩니다.
- 필드에 대해서
unique=True
를 지정한다면 자동으로 추가됩니다.
유효성 검사 예외
rest_framework.exceptions.ValidationError
를 사용하며 이는 응답 상태코드 400으로 처리합니다.
Serializer에서 유효성 검사 함수 지정
유효성 검사 함수는 model 에서 지정하는 것을 추천드립니다.
지금은 간단히 Serializer 에서 하는 예시를 하나 알아보도록 하겠습니다.
-
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
serializers.Serializer 가 아닌 serializers.ModelSerializer 의 경우에는 7번째 줄의 필드 지정 없이 Meta 클래스로 model과 fields 를 지정해주면 됩니다.
-
-
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
-
perfrom 함수
사용자에게 입력을 받은 후, 저장할 시에는 추가적인 정보와 함께 저장해야 하는 경우도 있습니다.
예를 들어 사용자로 부터 글의 제목을 받은 후 사용자의 ip 를 얻기 위해서는 이 정보를 사용자가 입력해야할까요?
그렇지 않습니다. 이는 따로 커스튬을 해줘야하는데 그 부분을 알아보도록 하겠습니다.
mixins 에서 CreateModelMixin
을 살펴보면 실질적인 저장은 perform_create
함수를 통해서 이루어지는 것을 알 수 있습니다.
# rest_framework/mixins.py
class CreateModelMixin(object):
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def perform_create(self, serializer):
serializer.save()
나머지도 이와 마찬가지입니다. 따라서 추가적인 커스튬이 필요하다면 perform 함수를 수정해줍니다.
- 생성 : perform_create
- 수정 : perform_update
- 삭제 : perform_destroy
아래와 같이 model 을 정의하고,
# 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)
title의 값만 사용자로 부터 받습니다.
# 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'])
'웹프로그래밍 > DRF' 카테고리의 다른 글
[Django] Throttling (0) | 2020.01.08 |
---|---|
[Django] Authentication 과 Permissions (0) | 2020.01.08 |
[Django] DRF Pagination (6) | 2019.12.30 |
[Django] filtering 과 Search (0) | 2019.12.29 |
[Django] format 과 Renderer (0) | 2019.12.29 |