[TIL_Carrotww] 71 - 22/12/13

μœ ν˜•μ„Β·2022λ…„ 12μ›” 13일
0

TIL

λͺ©λ‘ 보기
84/138
post-thumbnail

πŸ“Carrotww의 μ½”λ”© 기둝μž₯

🧲 μ‹€μ‹œκ°„ 인기 κ²Œμ‹œλ¬Ό

πŸ” μ‹€μ‹œκ°„ 인기 κ²Œμ‹œλ¬Όμ„ μ–΄λ–€ μ‹μœΌλ‘œ κ΅¬ν˜„ν•΄μ•Ό ν•˜λ‚˜ 고민을 많이 ν–ˆλ‹€.
ν˜„μž¬ ν”„λ‘œμ νŠΈμ— 인기 κ²Œμ‹œλ¬Όμž„μ„ κ°€λ₯΄λŠ” 기쀀은 두가지가 μžˆλ‹€.
μ’‹μ•„μš”μ™€ μ‘°νšŒμˆ˜μ΄λ‹€.

class Article(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='article_user')
    category = models.ForeignKey(Hobby, on_delete=models.CASCADE, related_name='article_category')
    title = models.CharField(max_length=500)
    content = models.TextField()
    article_image = models.ImageField(upload_to=rename_imagefile_to_uuid, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    like = models.ManyToManyField(User, blank=True, related_name='article_like')
    views = models.BigIntegerField(default=0)

like와 views κ°€ μ’‹μ•„μš”μ™€ 쑰회수 인데 ν•΄λ‹Ή ν•„λ“œ κΈ°μ€€μœΌλ‘œ 탑 10 κ²Œμ‹œλ¬Όμ„ 보여쀀닀면 orderby둜 views.pyμ—μ„œ μ •λ ¬ν•΄μ„œ ν”„λ‘ νŠΈλ‘œ 보내주면 끝일 것이닀.
ν•˜μ§€λ§Œ ν•œλ²ˆ 인기 κ²Œμ‹œλ¬Όμ€ μ‹œκ°„ μ œν•œμ΄ μ—†λ‹€λ©΄ 1달, 1λ…„κΉŒμ§€ 갈 수 μžˆμ„ 것이닀.
ν•΄μ„œ created_at으둜 μ‹œκ°„ λ°°μœ¨μ„ μ‘°μ •ν•œλ‹€λ©΄ λ°”κΏ€ 수 μžˆκ² λ‹€κ³  μƒκ°ν•˜μ˜€λ‹€.

λ˜ν•œ μƒˆλ‘œκ³ μΉ¨ λ•Œλ§ˆλ‹€ 인기 κ²Œμ‹œλ¬Όμ„ 점수λ₯Ό 맀기고 싢지 μ•Šμ•˜λ‹€. μš”μ²­μ΄ μžˆμ„λ•Œλ§ˆλ‹€ 연산이 μžˆμ„κ²ƒμ΄κ³  μ„œλ²„μ— 뢀담을 μ£ΌκΈ° μ‹«μ—ˆκΈ° λ•Œλ¬Έμ΄λ‹€

κ·Έλž˜μ„œ μƒκ°ν•œκ²Œ django crontab을 μ΄μš©ν•˜μ—¬ νŠΉμ • νŒŒμΌμ„ 30λΆ„λ§ˆλ‹€ μ‹€ν–‰μ‹œμΌœ 인기 κ²Œμ‹œκΈ€ 아이디듀을 μ •λ ¬ν•˜μ—¬ json 파일둜 μ €μž₯을 ν•΄λ†“μœΌλ©΄ μš”μ²­μ΄ λ“€μ–΄μ˜¬λ•Œ json 파일만 μ½μ–΄μ„œ 뿌렀주면 λ˜μ§€μ•Šλ‚˜? 라고 생각을 ν•˜μ—¬ 일단!
μ½”λ“œλ₯Ό μ§œλ΄€λ‹€.

articles app 에 μž„μ˜λ‘œ articlecron.pyλ₯Ό λ§Œλ“  ν›„ μ•„λž˜μ™€ 같이 μž‘μ„±ν•˜μ˜€λ‹€.

from datetime import datetime, timedelta
from .models import Article
from django.db.models import Q
import os, json
from pathlib import Path

# if __name__ == "__main__":
def get_score():
    category_score_dict = {1: 20, 2: 20, 3: 20, 4: 20, 5: 20, 6: 20, 7: 20, 8: 20, 9: 20}
    # 1 : 좕ꡬ 2 : 야ꡬ 3: μš”κ°€ 4: κ²Œμž„(λ‘€)
    # κ³Ό κ°™μ€μ‹μœΌλ‘œ μ·¨λ―Έ ν”Œλž«νΌμ΄μ§€λ§Œ μ–΄λ””μ—λ‚˜ μΈκΈ°μžˆλŠ” κ²Œμ‹œκΈ€μ΄λ‚˜
    # μΉ΄ν…Œκ³ λ¦¬κ°€ μžˆμ„ 수 μžˆμ–΄ μΈκΈ°μžˆλŠ” μΉ΄ν…Œκ³ λ¦¬λ§Œ 전체
    # 인기 κ²Œμ‹œκΈ€μ— μ˜¬λΌκ°€λ©΄ λΆˆκ³΅ν‰ ν•˜λ―€λ‘œ category별
    # 점수λ₯Ό 기본적으둜 μž‘μ•„μ£Όμ—ˆλ‹€.

    like_multiple = 1.2
    # μ’‹μ•„μš” κ°œμˆ˜μ— λ”°λ₯Έ μ μˆ˜μ΄λ‹€.
    # μ’‹μ•„μš” μ μˆ˜λŠ” μ‘°νšŒμˆ˜λ³΄λ‹€ 훨씬 λ†’μ•„μ•Ό λœλ‹€κ³  μƒκ°ν•˜μ§€λ§Œ
    # 아직 섀계 단계이기 λ•Œλ¬Έμ— λŒ€λž΅μ μœΌλ‘œ μ •ν•΄λ‘μ—ˆλ‹€.
    view_multiple = 1
    # 쑰회수 κ°œμˆ˜μ— λ”°λ₯Έ μ μˆ˜μ΄λ‹€.
    time_multiple = 0.2
    # μ‹œκ°„μ— λ”°λ₯Έ μ μˆ˜μ΄λ‹€ μ•„λž˜μ—μ„œ μ„€λͺ…ν•˜κ² λ‹€.
    current_time = datetime.now()
    # μ‹œκ°„μ— λ”°λ₯Έ 점수λ₯Ό 맀길 것이기에 ν˜„μž¬ μ‹œκ°„μ„
    # μ΄ˆκΈ°ν™” μ‹œμΌœλ†“μ•˜λ‹€.

    # μ·¨λ―Έ μΉ΄ν…Œκ³ λ¦¬λ³„ 점수
    def score(obj) -> int:
    # κ²Œμ‹œκΈ€ μ˜€λΈŒμ νŠΈκ°€ λ“€μ–΄μ˜€λ©΄ 점수λ₯Ό λ§€κΈ°λŠ” ν•¨μˆ˜μ΄λ‹€.
        result = 1
        result *= category_score_dict[obj.category.id]
        # μœ„μ—μ„œ μ„€λͺ…ν•œ μΉ΄ν…Œκ³ λ¦¬λ³„ μ μˆ˜μ΄λ‹€.
        result *= obj.like.count() * like_multiple
        # μ’‹μ•„μš”λŠ” many to many field μ—¬μ„œ countλ₯Ό ν•΄μ£Όμ–΄μ„œ
        # μ’‹μ•„μš” 개수λ₯Ό κ°€μ Έμ˜¨ ν›„ 배수λ₯Ό κ³±ν•΄μ£Όμ—ˆλ‹€.
        result *= obj.views * view_multiple
        # 쑰회수 μ μˆ˜μ΄λ‹€.

        hour_diff_sec = (current_time - obj.created_at).total_seconds() / 3600
        # ν˜„μž¬ μ‹œκ°„μ—μ„œ κ²Œμ‹œκΈ€μ΄ μž‘μ„±λœ μ‹œκ°„μ„ λΊ€ ν›„
        # total_seconds() ν•¨μˆ˜λ₯Ό μ΄μš©ν•˜λ©΄ μ΄ˆκ°€ λ‚˜μ˜¨λ‹€.
        # λ‚΄κ°€ μ›ν•˜λŠ” 것은 μ‹œκ°„μ΄κΈ° λ•Œλ¬Έμ— λΆ„ μ‹œ ν¬ν•¨ν•˜μ—¬
        # 3600으둜 λ‚˜λˆ„μ–΄μ£Όλ©΄ κΈ€ μž‘μ„± μ‹œκ°„λΆ€ν„° ν˜„μž¬μ‹œκ°„κΉŒμ§€
        # λͺ‡μ‹œκ°„ μ§€λ‚¬λŠ”μ§€ λ‚˜μ˜¨λ‹€

        # (10 - μ‹œκ°„λ°°μˆ˜ * μ‹œκ°„μ°¨μ΄(hours)) μ‹œκ°„λ‹Ή 0.2 배수 차이
        # ex) 1μ‹œκ°„ -> 9.8 , 2μ‹œκ°„ -> 9.6
        return result * (10 - (time_multiple * hour_diff_sec))
        # μœ„ exampleκ³Ό 같이 μ‹œκ°„λ³„λ‘œ 0.2 정도 차이λ₯Ό μ£Όκ³  μ‹Άμ–΄
        # μ‹œκ°„ 배수λ₯Ό 0.2둜 μ§€μ •ν•˜μ˜€λ‹€.
        # μœ„μ™€ 같은 λ°©μ‹μœΌλ‘œ 점수λ₯Ό 맀기면 였래된 κ²Œμ‹œλ¬Όμ€
        # μ—„μ²­λ‚œ μ‘°νšŒμˆ˜μ™€ μ’‹μ•„μš”λ₯Ό μ§€μ†ν•΄μ„œ λ°›μ•„μ•Ό μ‹€μ‹œκ°„
        # top κ²Œμ‹œκΈ€μ— 올라갈 수 μžˆμ„κ²ƒμ΄λ‹€.

    article_obj = Article.objects.filter(
        Q(created_at__gte=(datetime.now() - timedelta(days=2))) 
        &
        Q(updated_at__gte=(datetime.now() - timedelta(days=2))))
        # update_at은 λΉΌμ€˜λ„ λ κ±°κ°™μ§€λ§Œ 초기 μž‘μ„± μ‹œ
        # μˆ˜μ •λœκ²ƒλ„ ν¬ν•¨ν•˜μž λΌλŠ” μƒκ°μœΌλ‘œ 일단은 ν¬ν•¨μ‹œμΌœλ³΄μ•˜λ‹€.
        # ν•˜μ§€λ§Œ 점수λ₯Ό λ§€κΈ°λŠ” ν•¨μˆ˜μ—μ„œ 적용이 λ˜μ§€ μ•ŠκΈ°μ— μ§€κΈˆμ€
        # μ“Έλͺ¨ μ—†λŠ” μ½”λ“œμ΄λ‹€.
        # μœ„ μ½”λ“œλŠ” ν˜„μž¬ μ‹œκ°„λΆ€ν„° 이틀 μ•ˆμ— μž‘μ„±λœ κ²Œμ‹œκΈ€μ„ κ°€μ Έμ˜€λŠ” μ½”λ“œμ΄λ‹€.

    article_score_id_list = [(x, score(x)) for x in article_obj]
    # μ΅œμ’…μ μœΌλ‘œ νŒŒμΌμ— μ €μž₯λ˜λŠ” 값은 id만 λ˜μ–΄μ•Ό ν•˜μ§€λ§Œ 점수
    # κΈ°μ€€μœΌλ‘œ 정렬을 μ›ν•˜κΈ° λ•Œλ¬Έμ— μž„μ‹œλ‘œ
    # (κ²Œμ‹œκΈ€ 였브젝트, κ²Œμ‹œκΈ€ 점수) 둜 λ§Œλ“€μ–΄μ£Όμ—ˆλ‹€.

    article_score_id_list.sort(key=lambda x:x[1], reverse=True)
    # 점수 κΈ°μ€€μœΌλ‘œ μ •λ ¬

    result = {}

    result_id = [article_score_id_list[x][0].id for x in range(len(article_score_id_list))]
    # νŒŒμΌμ— μ €μž₯ν•˜κΈ° μœ„ν•΄ 점수 κΈ°μ€€μœΌλ‘œ μ •λ ¬λœ λ¦¬μŠ€νŠΈμ—μ„œ
    # 아이디 κ°’λ§Œ κ°€μ Έμ™€μ„œ λ‹΄μ•„μ€€λ‹€.

    result['result'] = result_id

    BASE_DIR = Path(__file__).resolve().parent.parent
    article_lank_file = os.path.join(BASE_DIR, 'article_lank.json')

    with open(article_lank_file, 'w') as f:
        json.dump(result, f, indent=4)
        # json ν˜•νƒœλ‘œ μ €μž₯ν•΄μ€€λ‹€.

get_score() ν•¨μˆ˜λŠ” λ‚˜μ€‘μ— main ν•¨μˆ˜λ‘œ λ°”λ€Œμ–΄ cron tabμ—μ„œ μ‹€ν–‰μ‹œν‚¬ 것이닀.

ν…ŒμŠ€νŠΈ κ²°κ³Ό 파일 μƒμ„±κΉŒμ§€ 잘 되며 viewμ—μ„œ κ°€μ Έμ˜€λŠ” λ‘œμ§μ€ 아직 μž‘μ„±ν•˜μ§€ μ•Šμ•˜λ‹€.
κ°€μ Έμ™€μ„œ λΏŒλ €μ£ΌλŠ”κ±΄ 쉽닀..γ…Žγ…Ž

crontab으둜 30λΆ„λ§ˆλ‹€ μ‹€ν–‰μ‹œμΌœμ£ΌλŠ” ν…ŒμŠ€νŠΈλ₯Ό 해보아야 ν•˜λŠ”λ° linux ν™˜κ²½μ—μ„œλ§Œ κ°€λŠ₯ν•˜κΈ° λ•Œλ¬Έμ— 일단은 import ν•˜μ—¬ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λŠ” μ‹μœΌλ‘œ μž„μ‹œ μž‘μ„±ν•˜μ˜€λ‹€.
λ‹€μŒμ£Όμ— 배포와 λ™μ‹œμ— ν…ŒμŠ€νŠΈλ₯Ό ν•˜λ €κ³  ν•œλ‹€.

ν‰μ†Œμ— crontab은 에전에 μ‚¬μš©ν•΄λ³΄μ•˜κΈ° λ•Œλ¬Έμ— 크게 λ¬Έμ œμ—†μ΄ 핸듀링 ν•  수 μžˆμ„ 것 κ°™λ‹€.

μ‹€μ œ μ‚¬μ΄νŠΈμ—μ„œλŠ” λ”μš± λ³΅μž‘ν•œ 둜직으둜 점수λ₯Ό λ§€κΈ°κ² μ§€λ§Œ, λ‚˜λŠ” μ „μ‚°, μˆ˜ν•™κ³Όκ°€ μ•„λ‹ˆκΈ° λ•Œλ¬Έμ—... λ‘œμ§μ€ μ–Έμ œλ“ μ§€ λ°”κΎΈλ©΄ λ˜λ‹ˆκΉŒ μƒκ°λ‚˜λŠ” λŒ€λ‘œ λ§Œλ“€μ–΄λ³΄κ³  μ‹Άμ–΄μ„œ μž‘μ„±ν•΄ λ³΄μ•˜λ‹€.
이제 workshop 뢀뢄도 μž‘μ„±ν•΄μ•Όμ§€...!
였늘 끝!

profile
Carrot_hyeong

0개의 λŒ“κΈ€