django 쿼리셋 ForeignKey 데이터 참조와 정렬

파오리·2021년 2월 24일
0

아주 작은 기록

목록 보기
7/13

문제 상황: ForeignKey로 연결되어 있는 테이블을 통해 정참조하여 연결된 테이블의 필드를 조건으로 정렬하고자 함

현재 상황


Nac의 userAccessor의 name으로 연결되어 있다.
내가 하고자 하는 것은
"검색필터를 통해 이미 한번 걸러진 Nac의 데이터 중에, user의 nac_count가 높은 것부터 순서대로 5개를 정렬"
하는 것이다.

*해당 목적으로는 잘못된 알고리즘으로, 이후 다시 짠 알고리즘과 코드 => 다시 한거
이 목적이 아니라, foreign key 데이터 참조를 위한 코드를 보기 위해서는 이 글이 맞음

# django views.py

...
nacList = nacList.filter(Q(time__icontains=search) | Q(user_id__name__icontains=search) |  
                        Q(ip__icontains=search) | Q(result__icontains=search) | Q(message__icontains=search))
                       
...

이렇게 검색필터를 통해 거르는거 까지는 해두었다.

시나리오

1) nacList의 user를 통하여 nacListAccessor의 공통된 데이터에 접근
2) 중복되는 Accessor 데이터는 제외
3) 모아진 데이터 (nacList에 들어있는 user들의 중복없는 Accessor 데이터 모음) 에서 nac_count를 내림차순으로 정렬
4) 상위 5개만 뽑기

결과

# django views.py

...
nac_access_rank = nacList.values('user_id__name').distinct().order_by('-user_id__nac_count')[:5]
...

하나 하나씩 순서대로 보면 이렇게 된다.

# nac_access_rank = nacList 일 경우
nac_access_rank = <QuerySet [<Nac: 2021-02-23 18:01:44>, <Nac: 2021-02-23 17:37:45>,
		<Nac: 2021-02-23 17:01:29>, <Nac: 2021-02-23 15:44:34>,
		<Nac: 2021-02-23 13:47:52>, <Nac: 2021-02-23 13:35:56>,
		<Nac: 2021-02-23 13:30:53>, <Nac: 2021-02-23 13:17:38>,
		<Nac: 2021-02-23 11:36:58>, <Nac: 2021-02-23 11:14:22>,
		<Nac: 2021-02-23 10:39:40>, <Nac: 2021-02-23 10:27:14>]>
  1. 필터링 된 결과 데이터에 대한 쿼리셋이 전달됨
# nac_access_rank = nacList.values('user_id__name') 일 경우
nac_access_rank = <QuerySet [{'user_id__name': 'aa'}, {'user_id__name': 'aa'}, 
			{'user_id__name': 'aa'}, {'user_id__name': 'aa'}, 
        		{'user_id__name': 'aa'}, {'user_id__name': 'aa'}, 
                	{'user_id__name': 'aa'}, {'user_id__name': 'aa'}, 
                    	{'user_id__name': 'aa'}, {'user_id__name': 'aa'}, 
                        {'user_id__name': 'aa'}, {'user_id__name': 'aa'}]>
  1. .values('user_id__name')에 주목!
    ForeignKey 를 통한 데이터 접근은 이와 같이 할 수 있다.
    검색을 통해 필터링된 결과 데이터의 user값을 통해 Accessor의 name필드값들을 불러온다.

    한 마디로 user를 통해 nacList와 Accessor의 공통된 데이터에 접근한 것이다.
    그러나 nacList에서 접근한 것이기 때문에 name이 중복되어 나온다.

# nac_access_rank = nacList.values('user_id__name').distinct().order_by('-user_id__nac_count') 일 경우
nac_access_rank = <QuerySet [{'user_id__name': 'a'}, {'user_id__name': 'b'}, 
			{'user_id__name': 'c'},{'user_id__name': 'd'},
            		{'user_id__name': 'e'},{'user_id__name': 'f'},
                    	{'user_id__name': 'g'}]>
  1. .order_by는 db필드를 통한 데이터 정렬에 쓰이는데, 나는 -user_id__nac_count를 통해 nacList의 user를 통해 접근한 Accessor테이블에서 nac_count를 내림차순으로 정렬했다.

    '-user_id__nac_count' ; 내림차순: 큰 수 -> 작은 수 (4,3,2,1)
    'user_id__nac_count' ; 오름차순: 작은 수 -> 큰 수 (1,2,3,4)

.distinct()는 중복 데이터를 제거하는 것인데, 'user_id__name'을 중복되지 않도록 해줬다.

# nac_access_rank = nacList.values('user_id__name').distinct().order_by('-user_id__nac_count')[:5] 일 경우
nac_access_rank = <QuerySet [{'user_id__name': 'a'}, {'user_id__name': 'b'}, 
			{'user_id__name': 'c'},{'user_id__name': 'd'},
            		{'user_id__name': 'e'}]>
  1. 이렇게 뒤에[:5] 를 붙이면 맨 처음 5개만 불러온다는 뜻이다.
# html

...
<h4 class="summary__card_info">
  🔍검색 결과 접근 top 5:
  </br>
  {% if nac_access_rank %}
    {% for rank in nac_access_rank %}
        {{forloop.counter}}위 <span class="search_result">{{rank.user_id__name}}</span>
    {% endfor %}
  {% endif %}
</h4>

마지막으로 html에서 템플릿 태그를 이용하여 데이터를 띄워주면

이렇게 순위대로 뜬다. (지금은 데이터가 3명꺼밖에 없어서 3개만 뜰 뿐)

성공 ~

profile
경험 == 배움

0개의 댓글