Programming/Django

[DRF] Serializer로 역참조의 역참조 모델 가져오기

stein 2021. 10. 22. 20:04

https://stein-log.tistory.com/27

 

Django foreign key를 사용했을 때 역참조(DRF)

결론부터 말하자면 참조하는 모델(ohlcv)과 참조되는 모델(share_announce)가 있을 때, 참조되는 모델.참조하는모델_set으로 접근가능하다. 이때, 참조하는 모델 foreign key 설정시 related_name을 설정해주

stein-log.tistory.com

지난 게시글에서는 1뎁스 역참조 필드를 어떻게 가져오는지 알아보았다.

이번에 만난 문제는

 

부모 모델을 참조하는

자식 모델을 참조하는

손자 모델을 

부모 모델의 serializer에서

참조하는 방법이다.

(복잡도 하다...)

 

아마 이렇게 까지 뎁스가 있는걸 굳이 serializer에서 해야하나 싶지만, 해당 serializer가 사용되는 모든 곳에서 손자 모델이 필요하기에 이 악물고 달려들어보았다.

 

그래서 어떻게 하는가

class ShareAnnounceSerializer(serializers.HyperlinkedModelSerializer):
    company_group = CompanyGroupMappingSerializer(source='publish_cmp.company_group', 
    	many = True, read_only=True)
	...
    
    class Meta:
        model = ShareAnnounce
        fields = ('company_group',...)

손자 모델의 serializer를 인자로 넣어주면 되는데, 이 때 source를 자식의 자식(자식.손자)라고 명시해주어야한다. 그렇지 않으면 해당 필드(company_group)자체가 반환되지 않는다(에러는 발생하지 않는다).

 

필자는 다음과 같이 실수하였다

class ShareAnnounceSerializer(serializers.HyperlinkedModelSerializer):
    company_group = CompanyGroupMappingSerializer(many = True, read_only=True)
    ohlcv = OHLCVSerializer(many = True, read_only=True)
    group_name = serializers.CharField(source='publish_cmp.company_group.name')
	...
    
    class Meta:
        model = ShareAnnounce
        fields = ('company_group','ohlcv','group_name',...)

1. 자식(ohlcv)과 동일한 방식으로 serializer를 추가

  -> 그냥 drf가 알아서 찾아준다고 생각했다;;; 작동하지 않는 이유는 publish_cmp밑에 company_group이 존재하기 때문에 찾지 못하는 것으로 추측된다.

2. 손자의 필드를 source로 찾으려함

  -> 현재 publish_cmp.company_group은 객체(serialized data)가 아니다.  따라서 값을 받아오지 못한다. (RelatedManager의 형태인 듯하다.) 다음이 위와 같이 코드를 작성했을 때 만나는 에러코드다.

Got AttributeError when attempting to get a value for field `group_id` on serializer `ShareAnnounceSerializer`. The serializer field might be named incorrectly and not match any attribute or key on the `ShareAnnounce` instance. Original exception text was: 'RelatedManager' object has no attribute 'id'.

따라서 company_group까지 source로 찾아서 serializer를 달아주는 것이, 위와같은 형태에서 최선으로 보인다. 왜냐하면 손자의 필드를 특정하기 위해서는 serialized된 데이터가 필요한데, 현재로서는 serialized된 데이터를 담아둘 곳이 없기 때문이다. 

아마 serializer의 특정 메소드를 오버라이딩하면 해결할 수 있을 것으로 보인다. 다음에 기회가 된다면 해당 작업을 포스팅하겠다.

 

📭 추신

분명 이것보다 더 나은 형태의 디자인이 존재할 것이다. 하지만 이 포스트로 serializer를 조금 더 이해하는데 도움이 되면 좋겠다.