본문 바로가기

개발/Django Restful Framework(drf)

DRF Serializer 알아보기

반응형

들어가기 전 간략한 설명

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
# Serializer란? 
#    복잡한 데이터를 쿼리셋 및 모델 인스턴스로 쉽게 변환 시키고,
#    이를 파이썬 데이터 타입에 맞춰 쉽게 렌더링 할 수 있게 해주는 것
 
# DRF Serializer에는 뭐가 있나
#    BaseSerializer, ListSerializer, ModelSerializer
 
# 언제 쓰나

# 어떻게 쓰나
# ModelSerializer + viewset 
# BaseSerializer + api_view 
 
# 뭐땜에 쓰나
# ModelSerializer
#    depth
# BaseSerializer  
#     to_representation()
#    
cs


그냥 되는대로 찾아서 DRF를 사용하다가 

1
2
3
Board 모델의 외래키인 user를 GET 할 땐, user의 특정 정보를 가져와주되, POST 시에는 pk로 넣고 싶어!
cs

라는 이유로 공부를 시작하게 되었다


DRF에서 Serializer는 

1
2
"복잡한 데이터를 쿼리셋 및 모델 인스턴스로 쉽게 변환 시키고,
이를 파이썬 데이터 타입에 맞춰 쉽게 렌더링 할 수 있게 해주는 것"
cs

이라고 한다


1
2
3
4
5
6
class BUser(AbstractBaseUser, PermissionsMixin):
    ...
 
class Board(models.Model):        
    user = models.ForeignKey('baseUser.BUser'null=True, blank=True, verbose_name=('유저'), related_name='users')       
    text = models.CharField(max_length=1000null=False, blank=False ,verbose_name='텍스트')
cs

위와 같이 User 모델과 Board 모델 을 만들고 

user를  Board의 외래키로 사용해야 할 때


어떻게 하면  목적을 달성할까 이래저래 사용 해봤다


ModelSerializer는 모델이라는 이름이 붙었듯이 모델을 가져와 사용하기 쉽게 되어 있다.

django의 form이 DB - form - web-form 형태로 DB와 web-form이 상호 작용을 하는데 이와 유사한 형태를 가진다 

또한 그런 이유로, Create나 Read가 서로 다른 동작을 한다던지 하는 경우에는 사용하지 않는것이 좋다

최종적으로 CRUD를 함께 사용하는 경우 사용하면 좋다


BaseSerializer는 기본적인 시리얼라이저인 만큼 커스텀을 해야하는 내용이 많거나,

또는 CRUD 중 단일 행동만 구현해도 괜찮은 경우 사용하기 좋다


ModelSerializer


  • Board와 BUser의 Create, Read가 같은 형태로 구현하는 경우,
  • 또는 Create시, Board와 BUser의 모든 필드를 한번에 생성하는 경우(Ex. 유저- 유저 프로필을 한번에 생성해야 할 때)
  • 관련 외래키(foreignKey)의 세부 내용이 전부 출력되도 괜찮은 경우 사용하면 좋다 


구현 상, 내가 가진 모든 필드를 그대로 보여주기 때문에 


Board Create시 자체 필드의 값을 넣어서 생성할 수 있다.

1
2
3
4
5
{
  "text""text값",
  "user": pk값
}
 
cs


Board Read시

1
2
3
4
5
{
  "text""3213",
  "user"2
}
 
cs

 와 같은 형태의 DB 그대로의 출력을 보여준다


이 때, user 외래키의 값을 보고 싶다면 

1
2
3
4
5
6
7
 
class BoardSerializer(serializers.ModelSerializer):     
    class Meta:        
        model = Board        
        depth = 1     
        fields = ('text','user')
 
cs

depth 라는 옵션을 사용해서 연결된 몇번째 외래키까지 보여줄 것인지 설정할 수 있다.


depth를 사용한 Read결과는 

1
2
3
4
5
6
7
8
9
10
11
12
13
[
    {
        "text""3213",
        "created_at""2016-04-26T09:30:13.795693Z",
        "user": {
            "username""test",
            "name""test",
            "profileImage""",
        }
    }
]
 
cs

위와 같이 user의 값을 보여주게 된다


다만 아쉽게도 depth로 보여주는 user의 데이터는 일부만 보여주고 나타내기는 어렵다


1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
class UserSerializer(serializers.ModelSerializer):    
    class Meta:        
        model = BUser       
        extra_kwargs = {'password': {'write_only': True}}        
        fields = ('username','name','profileImage')
 
class BoardSerializer(serializers.ModelSerializer):   
    user = UserSerializer(read_only=True,)    
    class Meta:        
        model = Board        
        depth = 1     
        fields = ('text','user')
 
cs

위와 같이 UserSerializer를 선언한 후, BoardSerializer에서 user를 선언 해주면,

Create 를 할 때, 한번에 Board와 User를 생성할 수 있다.


BaseSerializer

  • Board의 Read, 또는 Create 하나를 중점적으로 사용하는  API를 생성하는 경우,
  • 커스텀이 많이 들어가는 경우

사용하면 좋을 것으로 생각된다 


기본 함수 및 변수로는 아래와 같은 것들을 가진다 

.data

.is_valid()

.validated_data

.save()

.to_representation() //Read, 보여주기에 사용용

.to_internal_value() //Create 쓰기에 사용 

.create()

.update()


1
2
3
4
5
6
7
8
 
class UserSerializer(serializers.BaseSerializer):
    def to_representation(self, obj):
        return {
            'name': obj.name,
            'is_gender': obj.is_gender
        }
 
cs

유저의 특정 데이터만 가져오고 싶다면 위와 같은 형태의 구현으로 사용할 수 있다



ModelSerializer는 CRUD 모두와 함께하면 좋기 때문에 상대적으로 ViewSet과 어울리는 편이고,

BaseSerializer는 특정 기능별 api_view와 잘 어울리는 편이다


BaseSerializer의 경우 위의 UserSerializer를 

1
2
3
4
5
6
7
 
@api_view(['GET'])
def custom_user_data(request, pk):
    instance = BUser.objects.get(pk=pk)
    serializer = UserSerializer(instance)
    return Response(serializer.data)
 
cs

View단에서 불러와 사용하면 좋고


ModelSerializer의 경우

1
2
3
4
5
 class BoardViewSet(viewsets.ModelViewSet):    
    queryset = Board.objects.extra(       
         order_by=('created_at',)    
    )    
    serializer_class = BoardSerializer
cs

이와 같이 ModelViewSet과 함께 쓰면 사용하기 좋다 


1
2
3
4
5
6
7
from rest_framework import serializers    
    class BoardSerializer(serializers.ModelSerializer):    
        user_data = serializers.CharField(source='get_name', read_only=True)    
    class Meta:        
        model = Board        
        depth = 1
         ...
cs

와 같은 형태로 model의 def get_name(self): 를 불러오는 식으로 값을 가져올 수도 있다(이를 fields에 추가하면 이 값이 fields에 추가된다)


BaseSerializer는 to_internal_value(), to_representation으로 원하는 형태를 구성하는 반면,

ModelSerializer는 extra_kwargs, fields, read_only_fields, depth 등으로 형태를 구성한다


최종적으로


CRUD 상호 관계가 같은 경우 ModelSerializer를,

CRUD 중 특정 행동을 위한 API이거나, 커스텀이 많이 필요한 경우 BaseSerializer를 사용하면 되겠다

















반응형

'개발 > Django Restful Framework(drf)' 카테고리의 다른 글

DRF Serializer, Foreignkey  (0) 2016.04.26
djoser 패키지 (1)  (0) 2016.04.25
DRF write only field  (0) 2016.04.22
DRF url parameter filter 추가하기  (0) 2016.04.16
DRF Foreignkey Serializer에서 설정하기  (0) 2016.04.15