문제 상황: ForeignKey로 연결되어 있는 테이블을 통해 정참조하여 연결된 테이블의 필드를 조건으로 정렬하고자 함
Nac의 user
가 Accessor의 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
를 통하여 nacList
와 Accessor
의 공통된 데이터에 접근
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>]>
# 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'}]>
.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'}]>
.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'}]>
# 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개만 뜰 뿐)
성공 ~