[DRF Serializer] Handle Parsing Data

wandile·2022년 10월 19일
0

Pasing data to Serializing

외부 API에서 가져온 데이터를 파싱해 DB에 저장하기 위해 Serializer를 작성

외부 api를 통해서 가지고 온 데이터를 기반으로 서비스를 구성하기 위해 서비스가 제공하는 역할에 따라서 시나리오데 따라 DB구조를 먼저 정의하고,

추가될 수 있는 테이블을 고려해서 DB스키마를 구성하였다.

최종 데이터를 제공하기 위해서 간단하게 아래와 같은 테이블 구조가 필요했다.

데이터 베이스 스키마에는 서비스가 제공하는 데이터를 표현하기 위해서 1️⃣:1️⃣ 관계, 1️⃣:N 관계, M:N 관계를 모두 정의해주었다.

  • 테이블 B(N)와 1의 연관 관계를 가질 테이블 A
  • 테이블 D(N)와 1의 연관 관계를 가질 테이블 C
  • 테이블 A,C(N)와 1의 연관 관계를 가질 테이블 E
E가 표현해야할 데이터들의 구조 및 연관 구조
  • A (1)
    • B (N)
  • C (1)
    • D (N)
  • Mission
  • Robot
  • Action

  1. 서비스 데이터 표현 방식은 외부 API에서 가져온 데이터를 하나씩 파싱

  2. 여러개의 데이터가 Serializing대상이 된다면 Many옵션을 주어 처리하고, 역참조 관계에 있는(source = foo_set 옵션을 주어 부모 테이블인 Mission Report에서 자식테이블의 데이터를 가져오기 위해 처리.

  3. E의 Serializer를 정의한 후 save를 오버라이딩 해서 연관 구조를 가진 데이터가 하나의 테이블로 엮어 저장될 수 있게 구현하였다.

E의 연관관계를 Instance가 포함할 데이터 prefetch_realated로 가져오고 난 후

Mission, Robot, Action을 표현할 때 참조한 컬럼(id)을 표현하지 않고 참조 컬럼의 인스턴스를 표현하기 위해서 to_representation을 오버라이딩.

-> to_representation으로 Instance를 표현하는 방법을 몰라서 맞는 쿼리와 Serializer구조를 만들었음에도 불구하고 결과에서는 값들이 나타나지 않거나 Id값 만이 표현되는 현상을 해결할 수 있었다. ⭐️

  • E_Serializer(instance=instance.mission).data 와 같은 형식으로
    • 각각 해당하는 instance의 .data를 serializing하여 표현
    • Instance에는 mission, robot, action, A가 포함되어 있기 때문

만약 오버라이딩 하지 않는다면 ID가 표현됨

얻은 경험

서비스 데이터를 제공하기 위해 연관관계 테이블의 데이터를 표현하는 과정에 Instance에 담긴 데이터를 표현하기 위해 Query작성, 시리얼라이저 작성 과정을 이해하기 좋은 예제였고

서비스를 전체적인 관점에서 파악하여야 그에 맞는 DB 스키마를 구성할 수 있고 확장이 용이한 형태로 설계할 수 있다.

이전에 비해 좁은 시야에서 보다 넓은 시야에서 구조를 먼저 생각하고 구현할 수 있는 경험이었다.

외부 API에서 얻은 데이터 바탕으로 제공 할 서비스에 맞게 단일 테이블, 연관 테이블구조를 가진 DB스키마를 구성하면서 시행착오를 겪었는데

  1. 먼저 1:N 관계에서 최종 데이터 하나에 여러개의 데이터가 포함되어야 했기 때문에 Foreign key로 엮어야 할 상황에 모델을 반대로 정의했다. 이후 Parsing데이터를 저장하는 과정에서 실수를 발견해 다시 모델을 수정할 수 있었다.

→ ManyToMany, OneToMany, OneToOne관계를 가진 테이블 구조를 비즈니스 상황에 맞게 설계할 수 있다.

  1. 테이블 마다 엮인 제약관계에서 null값이 될 수 있는 데이터가 있지만 Null Constraint를 위반하지 않기 위해 null을 허용해야 하는 상황이 발생 하는데,

이는 Model에서 null, brank를 True로 세팅하고 Serializer에서 serialize 과정에서 parsing할 데이터를 모델과 맞추기 위해 extra_kwargs 속성, serialize 필드에서 required를 False로 바꾸어 주면 됐다.

  1. 역참조 관계에 있는 데이터를 시리얼라이징할 때 Serializer field명에 _set을 주기 보다는 source를 related_name으로 설정하거나 field_set으로 설정하는 것이 안전하고, Meta에 정의 할 field명에 Serializing과정에서 겹치고 명확하지 않은 args를 참조하는 것을 방지하기 위해서도 source 속성으로 역참조 관계를 lookup 해주어야 한다.

DRF Practice.

You'll normally want to ensure that you've set an appropriate related_name argument on the relationship, that you can use as the field name. For example:

class Track(models.Model):
    album = models.ForeignKey(Album, related_name='tracks', on_delete=models.CASCADE)
    ...

If you have not set a related name for the reverse relationship, you'll need to use the automatically generated related name in the fields argument. For example:

class AlbumSerializer(serializers.ModelSerializer):
    class Meta:
        fields = ['track_set', ...]

0개의 댓글