일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- Code Refactoring
- 동적계획법
- programmers
- 코딩테스트
- graph
- 프로그래머스
- 완전탐색
- DP
- sort
- Greedy
- 알고리즘
- 문자열
- 힙
- BFS
- DVWA
- binary search
- 카카오 기출
- 정렬
- string
- Dynamic Programming
- django
- 그래프
- heap
- Brute Force
- 탐욕법
- Algorithm
- 백준
- Queue
- DFS
- 큐
- Today
- Total
생각과 고민이 담긴 코드
Nested Serializer - Django Rest Framework 본문
현재 공모전에서 모바일 애플리케이션을 개발하면서 DRF를 활용하여 REST API를 만들고 있다.
하나의 Reivew에 여러 Tag들이 들어가는 기능을 개발하고 있고
그에 따라 Review 테이블은 Tag 테이블과 1:N 관계를 갖는다.
다음은 그렇게 구현된 Model의 코드이다.
위 코드를 보면 1:N 관계를 정의하기 위해 Tag 테이블 쪽에 review의 id를 FK로 정의한 것을 알 수 있다.
그런데 상황에 따라서 각 테이블의 CRUD API를 각각 만들 수 없는 경우가 존재한다.
예를 들어, 한 화면에서 모든 리뷰들을 불러올 때 각 리뷰들의 태그들도 한 번에 보여줘야 할 때나
리뷰를 생성할 때 태그들도 한 번에 생성시켜야 할 때는 related realation들의 data들을 한 번에 처리해줘야 할 필요성이 있다.
그러한 상황들을 처리하기 위해 DRF에서는 Nested Serializer 기능을 제공한다.
말이 어려워 보이지만 JSON 데이터 형식을 떠올리면 이해가 쉽다.
{
"content": "용기가 좀 작았네.",
"store":2,
"user": 6,
"tag": [
{
"tag_content": "크레이프케익",
"type": 1,
"color_index": 150000
},
{
"tag_content": "560ml",
"type": 2,
"color_index": 150000
}
]
}
위와 같이 프론트엔드에서 JSON 데이터를 구성해서 보낸다고 생각해보자.
가장 상위에 있는 데이터들은 review 테이블에 들어가는 데이터들이고
Tag data는 "tag" 하위의 리스트 형태로 나열되어있다. 이러한 형태를 Nested(중첩된) 형태라고 하고
Nested Serializer는 이러한 중첩된 JSON 데이터를 1:N 테이블 구조로 인식하여
각각 테이블에 알맞게 데이터를 deserialize 시켜 DB에 넣어준다.
그렇다면 이제 Nested Serializer의 사용법을 알아보자. 먼저 각 테이블에 관한 serializer class를 각각 만들어준다.
Review 테이블, Tag 테이블, ReviewImg 테이블이 있다면
ReviewSerializer, TagSerializer, ReviewImgSerializer들을 각각 만들어줘야 한다.
참고로 여기서 ReviewImg 테이블도 Tag 테이블과 마찬가지로 Review 테이블과 1:N 관계를 이룬다.
그런 다음 ReviewSerializer 내에서 TagSerializer와 ReviewImgSerializer를 변수에 할당시켜서
fields에 명시해놓으면 된다. 이렇게 하면 GET을 통해 아래와 같이 여러 테이블의 중첩된 데이터를 반환받을 수 있다.
그렇다면 중첩된 JSON 데이터를 받아서 Nested Serializer을 활용하여 데이터를 저장시키려면 어떻게 해야 할까?
아까 봤던 코드를 다시 봐보면 ReviewImgSerializer에는 인자로 "read_only = True" 넣어준 것을 볼 수 있다.
즉, ReviewImgSerializer는 GET을 통한 Read만 가능하게 한다는 뜻이고 TagSerializer는 생성, 수정, 삭제도 가능하게 하려면 해당 인자는 빼줘야 한다.
그리고 생성을 가능하게 하기 위해선 추가적으로 ReviewSerialzier 내에서 create() 함수를 오버라이드 해야 한다.
공식문서에서 나온 대로 따라서 구현했으며 참고 링크는 포스팅 마지막에 남겨 놓았다.
코드를 간단히 보면 입력으로 받은 dictionary 객체(받은 json 데이터를 파싱 한 것)에서 'tag' key로 받은 리스트를
pop을 통해 따로 빼준다. (위에 있는 JSON 데이터를 보시면 이해가 쉽다.)
그리고 tag 데이터가 빠진 review 데이터로 Review 테이블의 리뷰 객체를 만들고 해당 리뷰 객체를 항상 첫 번째 인자로 넣어주면서 리스트에 있는 모든 tag 데이터들을 테이블에 저장시켜준다.
결과적으로 위처럼 의도한 대로 잘 생성된 것을 확인할 수 있다.
Reference:
https://www.django-rest-framework.org/api-guide/relations/#writable-nested-serializers
Serializer relations - Django REST framework
www.django-rest-framework.org