Serializer_응용 - KEEMSY/DRF_AFTER_CLASS Wiki

Serializer 응용

역참조

외래키를 사용해 참조하는 object를 역으로 찾는다.

  • 외래키 지정 시 related_name 설정을 통해 역참조 시 사용될 이름을 지정한다.
  • related_name을 설정하지 않는다면 기본적으로 tablename_set 형태로 지정된다.

user_profile.hobby -> 정참조

hobby.userprofile_set -> 역참조

foreignkey, many-to-many

  • 한 object를 여러 object에서 참조 가능하다.(한개의 hobby object를 여러개의 userprofile에서 참조 가능하다.
  • 특정 hobby object에서 userprofile_set을 사용하여 역참조 할 경우, 데이터는 object가 아닌 queryset으로 보여진다.
# Hobby model에서 무작위 object를 지정
hobby = HobbyModel.objects.all().order_by("?").first()

# userprofile_set은 many to many기 때문에 queryset 형태
# 아래와 같이 사용 할 경우 hobby object를 참조하는 모든 userprofile을 return
# .all()을 붙여주지 않으면 user.UserProfile.None와 같은 형태로 return됨
hobby_users = hobby.userprofile_set.all()

# queryset 형태기 때문에 필요에 따라 특정 filter를 걸어 줄 수도 있다.
hobby_users = hobby.userprofile_set.filter(field=value)

역참조를 활용한 같은 취미를 가진 사람을 찾는 코드

def get(self, request):
	user = request.user
	hobbys = user.userprofile.hobby.all()
	for hobby in hobbys:
	# exclde : 매칭 된 쿼리만 제외, filter와 반대
        # annotate : 필드 이름을 변경해주기 위해 사용, 이외에도 원하는 필드를 추가하는 등 다양하게 활용 가능
	# values / values_list : 지정한 필드만 리턴 할 수 있음. values는 dict로 return, values_list는 tuple로 ruturn
	# F() : 객체에 해당되는 쿼리를 생성함
            hobby_members = hobby.userprofile_set.exclude(user=user).annotate(username=F('user__username')).values_list('username', flat=True)
            hobby_members = list(hobby_members)
            print(f"hobby : {hobby.name} / hobby members : {hobby_members}")

# result print
"""
hobby : 산책 / hobby members : ['user1']
hobby : 음악감상 / hobby members : ['user1', 'user2']
hobby : 스쿠버다이빙 / hobby members : ['user2']
hobby : 여행 / hobby members : ['user2']
"""