본문 바로가기
카테고리 없음

DRF 역참조[2]

by abccoco 2022. 6. 23.

역참조 물론 한번 작성했지만 자시 정리하자!

 

 

역참조를 사용할때는 one-to-one 필드가 아닌 경우는 데이터를 set으로 받아 주어야 한다.

one-to-many, many-to-many 같은 경우는 여러 유저의 정보를 가져오므로 생각해보면 당연한것도 같다.

  • 역참조할 대상을 정할때는 테이블 뒤에 _set을 붙여준다.
  • _set을 해서 데이터를 가져오는 경우 데이터는 쿼리셋 형태로 가져오게 된다.
  • _set.filter() 를 사용해서 원하는 데이터만 가져올 수도 있다.
  • related_name 역참조 별칭을 내가 원하는데로 정할 수 있다.

 

  • 기본 역참조 예시 코드
# 역참조를 해서 해당 user의 UserProfile.hoby를 가져오는 경우로 예시를 들겠다.

# 역참조 안한 경우
user_profile = UserProfile.objects.get(user=user)
hobbys = user_profile.hobby.all()

# 역참조를 하는 경우
hobbys = user.profile_set.hobby.all()

 

  • 역참조 활용

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

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']
"""

 

annotate, values_list 사용법

serlilzer 사용하면 대부분의 경우 대체 가능

# 이 코드를 풀어서 보도록 하자
hobby_members = list(hobby.userprofile_set.exclude(user=user).annotate(username=F('user__username')).values_list('username', flat=True))

# exclude를 사용해서 나의 취미를 제외해 준다
hobby.userprofile_set.exclude(user=user)

# userprofile의 user 필드의 username을 username안에 저장한다
hobby.userprofile_set.exclude(user=user).annotate(username=F('user__username'))

# 가져온 데이터중 username만 뽑는다
hobby.userprofile_set.exclude(user=user).annotate(username=F('user__username')).values_list('username')

# flat=True를 통해 튜플 형태의 데이터를 리스트 형식으로 바꾸어 준다. 프린트하면 쿼리셋의 리스트 형식
hobby.userprofile_set.exclude(user=user).annotate(username=F('user__username')).values_list('username', flat=True)

# 데이터가 쿼리셋 형태이므로 보기쉽게 리스트 형식으로 바꾸어 준다. 프린트 하면 그냥 리스트 형식
list(hobby.userprofile_set.exclude(user=user).annotate(username=F('user__username')).values_list('username', flat=True))

  • 기타

F의 설명

# 참고로 F를 사용하려면 'import F' 를 해주어야 한다.

# F 안에 들어 있는 str을 query로 바꾸어 준다.
F('user__username')

 

댓글