serializer ์ฌํ
serializer๋ ๋ฐ์ดํฐ ์ง๋ ฌํ ์ธ์๋ data validation, create, update ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์๋ค.
validator
serializer์์๋ ๊ธฐ๋ณธ์ ์ผ๋ก Meta class ๋ด๋ถ field์ ํฌํจ๋์ด ์๋ ํญ๋ชฉ์ ๋ง๊ฒ validate๋ฅผ ์งํํ๋ค
๐งฉ ์ ์ฉ ์์
# views.py
from user.serializers import UserSerializer
...
class UserView(APIView):
def post(self, request):
# serializer์ data ์ธ์์๋ model๋ก ์ง์ ๋ ํ
์ด๋ธ์ field:value๋ฅผ dictionary๋ก ๋๊ฒจ์ค๋ค.
user_serializer = UserSerializer(data=request.data)
# serializer validator๋ฅผ ํต๊ณผํ์ง ์์ ๊ฒฝ์ฐ .is_valid()๊ฐ False๋ก return๋๋ค.
if user_serializer.is_valid():
# validator๋ฅผ ํต๊ณผํ์ ๊ฒฝ์ฐ ๋ฐ์ดํฐ ์ ์ฅ
user_serializer.save()
return Response({"message": "์ ์"}, status=status.HTTP_200_OK)
# .errors์๋ validator์ ์คํจํ ํ๋์ ์คํจ ์ฌ์ ๊ฐ ๋ด๊ฒจ์ ธ ์๋ค.
return Response(user_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# sample request.data
"""
{
"username": "new_user",
"password": "MyL0ve1yP@ssw0rd",
"fullname": "myname",
"userprofile": {
"introduction": "์๊ธฐ์๊ฐ์
๋๋ค.",
"birthday": "2000-1-01",
"age": 30
},
"trash": "zczxcvx"
}
"""
๐งฉ ์ ์ฉ ์์
class UserSerializer(serializers.ModelSerializer):
# ์ธ๋ ํค ๊ด๊ณ์ ์๋ ํ๋์ required๋ฅผ ์ค์ ํ๊ณ ์ถ์ ๊ฒฝ์ฐ ์ธ์๋ก ๋๊ฒจ์ค์ผ ํ๋ค.
userprofile = UserProfileSerializer(required=False) # default : True
...
class Meta:
...
# ๊ฐ ํ๋์ ํด๋นํ๋ ๋ค์ํ ์ต์
์ง์
extra_kwargs = {
# write_only : ํด๋น ํ๋๋ฅผ ์ฐ๊ธฐ ์ ์ฉ์ผ๋ก ๋ง๋ค์ด ์ค๋ค.
# ์ฐ๊ธฐ ์ ์ฉ์ผ๋ก ์ค์ ๋ ํ๋๋ ์ง๋ ฌํ ๋ ๋ฐ์ดํฐ์์ ๋ณด์ฌ์ง์ง ์๋๋ค.
'password': {'write_only': True}, # default : False
'email': {
# error_messages : ์๋ฌ ๋ฉ์ธ์ง๋ฅผ ์์ ๋กญ๊ฒ ์ค์ ํ ์ ์๋ค.
'error_messages': {
# required : ๊ฐ์ด ์
๋ ฅ๋์ง ์์์ ๋ ๋ณด์ฌ์ง๋ ๋ฉ์ธ์ง
'required': '์ด๋ฉ์ผ์ ์
๋ ฅํด์ฃผ์ธ์.',
# invalid : ๊ฐ์ ํฌ๋งท์ด ๋ง์ง ์์ ๋ ๋ณด์ฌ์ง๋ ๋ฉ์ธ์ง
'invalid': '์๋ง์ ํ์์ ์ด๋ฉ์ผ์ ์
๋ ฅํด์ฃผ์ธ์.'
},
# required : validator์์ ํด๋น ๊ฐ์ ํ์ ์ฌ๋ถ๋ฅผ ํ๋จํ๋ค.
'required': False # default : True
},
}
๐งฉ ์ ์ฉ ์์
# serializer์ ์ธ์์ object๋ฅผ ๋ฃ์ด ์ง๋ ฌํ ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋ค.
user = request.user
return Response(UserSerializer(user).data, status=status.HTTP_200_OK)
# object์ ๋ง์ฐฌ๊ฐ์ง๋ก queryset์ ์ธ์๋ก ๋ฃ์ด ์ฌ๋ฌ๊ฐ์ ์ง๋ ฌํ ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋ค.
hobbys = Hobby.objects.all()
# queryset์ ์ธ์๋ก ๋ฃ์ ๊ฒฝ์ฐ many=True ์ค์ ํ์ํ๋ค.
return Response(HobbySerializer(hobbys, many=True).data, status=status.HTTP_200_OK)
# partial์ True๋ก ์ค์ ํ ๊ฒฝ์ฐ required field์ ๋ํ validation์ ์ํํ์ง ์๋๋ค.
# ์ฃผ๋ก ์ผ๋ถ ํ๋๋ฅผ update ํ ๋ ์ฌ์ฉ๋๋ค.
user_serializer = UserSerializer(data=request.data, partial=True)
# raise_exception์ True๋ก ์ค์ ํ ๊ฒฝ์ฐ validation์ ํต๊ณผํ์ง ๋ชปํ์ ๋ exception์ ๋ฐ์์ํจ๋ค.
user_serializer = UserSerializer(data=request.data, raise_exception=True)
๐งฉ ์ ์ฉ ์์
class UserSerializer(serializers.ModelSerializer):
...
# validate ํจ์ ์ ์ธ ์ serializer์์ ์๋์ผ๋ก ํด๋น ํจ์์ validation์ ํด์ค
def validate(self, data):
# custom validation pattern
if data.get("userprofile", {}).get("age", 0) < 12:
# validation์ ํต๊ณผํ์ง ๋ชปํ ๊ฒฝ์ฐ ValidationError class ํธ์ถ
raise serializers.ValidationError(
# custom validation error message
detail={"error": "12์ธ ์ด์๋ง ๊ฐ์
ํ ์ ์์ต๋๋ค."},
)
# validation์ ๋ฌธ์ ๊ฐ ์์ ๊ฒฝ์ฐ data return
return data
serializer๋ฅผ ๋ฐฐ์ฐ๋ฉด์ ๋ง์ ๊ธฐ๋ฅ๋ค๊ณผ ๋ฌธ๋ฒ๋ฑ์ ์ดํด๋ดค๋๋ฐ, ๊ทธ๋์ ๋ณด์ง ๋ชปํ๋ ๊ธฐ๋ฅ ๋ค์ด ๋ง์์ ํ ๋ฒ์ ์ต๋ํ๋๋ฐ์๋ ๋ฌด๋ฆฌ๊ฐ ์๋ ๊ฒ ๊ฐ๋ค. ์์ผ๋ก ํ๋ก์ ํธ๋ฅผ ์งํํ๋ฉด์ ํ์ํ ๋ถ๋ถ๋ง๋ค ์ง์ ์ฐพ์๋ณด๋ฉด์ ์ต์ํด์ ธ์ผ ํ ๊ฒ ๊ฐ๋ค. ๊ทธ๋ฆฌ๊ณ ๊ณ์ ๋ฐฐ์ฐ๋ ๊ฒ ์ถ์ ๋ ๋๋ง๋ค ์ํํด์ผ ํ ์์ด ๋ง์์ง๊ฒ ๋๋ฉด์ ๋ฒ ์ฐจ๊ธฐ๋ ํ์ง๋ง, ๊ณ์ ๋ณต์ตํ๊ณ ๋ง์ด ์ ํด์ ์ต์ํด์ง๋๊ฒ๋ง์ด ์ค๋ ฅ์ ๊ธฐ๋ฅผ ์ ์๋ ๊ธธ์ด๋ผ๊ณ ์๊ฐํ๋ค.