T.I.L May 17, 2023 (DRF 모델간 관계(참조)에 관해 겪던 문제 해결)

2023. 5. 17. 09:31T.I.L (Today_I_Learned)

문제점


2023.05.15 - [T.I.L (Today_I_Learned)] - T.I.L May 12, 2023 (DRF 팀 프로젝트 중 모델들의 관계에 대해 어려움을 겪고 있습니다.)

 

T.I.L May 12, 2023 (DRF 팀 프로젝트 중 모델들의 관계에 대해 어려움을 겪고 있습니다.)

어려움을 겪고 있는 문제 users앱 User모델 더보기 # 사용자 기본 모델 class User(AbstractBaseUser): user_name = models.CharField('ID', max_length=30, unique=True, error_messages={"unique": "이미 사용 중이거나 탈퇴한 사용자

sapiens94.tistory.com

문제가 되는 모델들의 관계는 아래와 같습니다.

UserProfile과 Post가 서로를 직접 참조하고 있지는 않지만, User를 사이에 두고 UserProfile과 Post가 서로를 참조할 수 있습니다.

 

 

아래는 기존의 코드입니다. 

# 기존 코드
class UserFeedPageSerializer(serializers.ModelSerializer):
		...
	user_posts = PostSerializer(many=True, read_only=True)
    	...
        
	class Meta:
    	model = UserProfile
        fields = (
        	...
            "user_posts",
            ...
        )

Post 모델의 필드가 사용되는 PostSerializer를 불러와 user_post에 담고 활용하면 될 것이라는 아이디어로 작성한 코드 입니다.

UserProfile이 Post를 직접 참조하고 있지 않다는 것 까지는 인지했지만 그 관계를 어떻게 코드로 구성해야 할지 몰랐습니다.

 

 

문제 해결


아래는 수정된 코드 입니다.

# 수정된 코드
# 사용자 피드 페이지 serializer
class UserFeedPageSerializer(serializers.ModelSerializer):
		...
	user_posts = serializers.SerializerMethodField()
    	...
    
    def get_user_posts(self, obj):
    	user_id = obj.user.id
        posts = Post.objects.filter(author_id=user_id)
        posts = PostSerializer(posts, many=True).data
        return posts
    
    class Meta:
        model = UserProfile
        fields = (
            ...
            "user_posts",
            ...
        )

위에서 설명한 것 처럼 UserProfile 모델은 Post 모델과 서로 직접 참조를 하고 있지 않습니다.
따라서 PostSerializer를 불러와 필드로 만들어 정의해도 Serializer가 Post 모델 자체를 인식하지 못하기 때문에 UserProfile 모델에 필드로 추가되지 않던 이슈였습니다.
=> SerializerMethodField에 정의된 method를 호출하여 인자 값인 obj를 이용해 내가 사용하고 싶은 Post 객체들을 가져와야 합니다.

=> def get_user_posts method의 인자 값인 obj는 UserFeedPageSerializer가 사용하고 있는 UserProfile 모델의 객체입니다.

=> posts라고 정의한 변수에 해당되는 아이디 값을 가진 Post 모델의 객체들을 전부 담습니다.

=> 다시 정의한 posts 변수에 이전 posts의 값을 PostSerializer에 인자 값으로 넣고 그 결값을 return 합니다.

 

 

 

알게된 것


1. 직접 참조가 아닐 경우 SerializerMethodField(모델에 없는 필드를 추가하고 싶거나, 모델에 있는 값을 변형해서 새로운 필드 값으로 넣기 위해 사용)를 사용하여 해결할 수 있는 것을 알게 되었습니다.

 

2. SerializerMethodField()

    - 모델에 없는 필드를 추가하고 싶거나, 모델에 있는 값을 변형해서 새로운 필드 값으로 넣기 위해 사용

 

3. SerializerMethodField()안에 정의된 method의 인자값 중 obj가 의미하는 것

    - 해당 Serializer가 사용하는 모델의 객체입니다.

 

 

-끝-


문제 해결을 도와주시고 또다른 방법에 대한 힌트를 주신 기술 매니저님 감사합니다.

해결 후 해결 방법을 궁금해 해주신 팀원 분들 감사합니다.

또다른 방법에 대한 자료를 제공해 주신 동기님 감사합니다.