lazy한 쿼리셋
쿼리셋이 중복되어 실행되는 것을 최적화 하기 위해서는 결과를 변수에 저장해서, 저장된 것을 재활용 하는 방법을 쓸 수 있다. lazy 한 쿼리셋이라고 부르면 된다.
list()함수를 사용해 리스트로 변환하고 저장한 값으로 사용이 가능하다.
match_applys = MatchApply.objects.filter( user=user, schedule__gte=start_date, schedule__lte=end_date, ) match_applys = list(match_applys) # 재사용 players = ( MatchApply.objects.filter( match_id__in=[match_apply.match_id for match_apply in match_applys], # DB HIT POINT ) .exclude(user=user) .annotate(count=Count("user_id")) .order_by("-count", "name")[:3] ) personal_data = { "appearances": len(match_applys), # DB HIT POINT }
filter에서는 DB 조회를 하지 않는다. 사용 시에 조회하게 되는데, list()로 감싸 lazy하게 만들면 DB를 조회하지 않고 변수에 저장된 객체를 사용할 수 있게 된다.
모델 정의 시, 같은 모델이 있으면 에러가 발생한다.
모델 내부를 정의할때, 같은 모델(예를 들면 User)가 여러개 있다면, 마이그레이션 시 오류를 뱉는다.
SystemCheckError: System check identified some issues: ERRORS: team.Vote.elected_user: (fields.E304) Reverse accessor for 'Vote.elected_user' clashes with reverse accessor for 'Vote.vote_user'. HINT: Add or change a related_name argument to the definition for 'Vote.elected_user' or 'Vote.vote_user'. team.Vote.vote_user: (fields.E304) Reverse accessor for 'Vote.vote_user' clashes with reverse accessor for 'Vote.elected_user'. HINT: Add or change a related_name argument to the definition for 'Vote.vote_user' or 'Vote.elected_user'.
class Vote(models.Model): elected_user = models.ForeignKey( User, related_name="elected_in_player_of_the_year_votes", on_delete=models.SET_NULL, null=True, ) vote_user = models.ForeignKey( User, related_name="cast_in_player_of_the_year_votes", on_delete=models.SET_NULL, null=True, ) created_at = models.DateTimeField(verbose_name="생성일", null=True, auto_now_add=True)
related_name을 설정하면 해결이 가능하다. user.selected_user.all()로 데이터를 가져올 수 있다. 하지만 딱히 쓸모는 없어 보인다.
댓글