8. 디테일 업그레이드 ( 조회수 쿠키 & Humanize)

[STEP 8] 디테일 업그레이드 (조회수 쿠키 & Humanize)

본 카테고리의 마지막 단계입니다.

조회수 중복 증가(F5 연타)를 방지하고, "방금 전", "5분 전" 같은 날짜 표시를 적용합니다.

1. 설정 추가 (config/settings.py)

config/settings.py 를 열어 날짜를 사람이 보기 편하게 바꿔주는 humanize 앱을 등록합니다.

INSTALLED_APPS = [
    # ... 기존 앱들 ...
    'django.contrib.staticfiles',
    'django.contrib.humanize', # [추가]
    # ...
]

# (참고) 언어 설정이 한국어여야 "방금 전"으로 나옵니다.
LANGUAGE_CODE = 'ko-kr'
⚠️ 중요: 서버가 실행 중이라면 설정 파일을 수정했으므로 서버를 재시작해 주세요.

2. 로직 수정 (boards/views.py)

쿠키(Cookie)를 사용하여 "오늘 하루 동안은 같은 글의 조회수를 1번만 증가"시키도록 로직을 변경합니다.

boards/views.pyboard_detail 함수를 수정하세요.

# [import 추가]
from django.utils import timezone
from datetime import datetime, timedelta, time

def board_detail(request, board_code, pk):
    board = get_object_or_404(Board, code=board_code)
    post = get_object_or_404(Post, pk=pk, board=board)
    
    # 1. 쿠키 이름 정의 (게시글마다 달라야 함)
    cookie_name = f'hitboard_{board_code}_{pk}'
    
    # 2. 응답 객체 미리 생성 (쿠키를 심기 위해)
    # select_related('author'): 댓글 작성자 정보를 한 번에 가져와서 DB 성능 최적화
    response = render(request, 'boards/board_detail.html', {
        'board': board,
        'post': post,
        'comments': post.comments.select_related('author').all(), 
        'form': CommentForm()
    })

    # 3. 쿠키 확인: 쿠키가 없을 때만 조회수 증가
    if request.COOKIES.get(cookie_name) is None:
        post.views += 1
        post.save()
        
        # 4. 쿠키 유효기간 설정 (오늘 밤 자정까지)
        tomorrow = datetime.now() + timedelta(days=1)
        midnight = datetime.combine(tomorrow, time.min)
        expires = (midnight - datetime.now()).total_seconds()
        
        # 쿠키 심기
        response.set_cookie(cookie_name, 'true', max_age=expires)
        
    return response

3. 화면 수정 1 - 메인 대시보드 (templates/home.html)

메인 화면(templates/home.html)의 게시글 목록에 작성 시간(naturaltime)을 추가합니다.

{% extends 'base.html' %}
{% load humanize %} {% block content %}
<div class="row mt-2">
    <div class="col-md-6 mb-4">
        <div class="card h-100">
            <div class="card-header bg-light">
                <i class="bi bi-clock"></i> <strong>자유게시판 최신글</strong>
            </div>
            <ul class="list-group list-group-flush">
                {% for post in free_posts %}
                <li class="list-group-item d-flex justify-content-between align-items-center">
                    <a href="{% url 'boards:board_detail' post.board.code post.pk %}" class="text-decoration-none text-dark text-truncate" style="max-width: 75%;">
                        {{ post.title }}
                        
                        <span class="small text-muted ms-1">
                             {{ post.created_at|naturaltime }}
                        </span>
                    </a>
                    <div class="small text-muted">
                        {{ post.author.username }}
                    </div>
                </li>
                {% empty %}
                <li class="list-group-item text-center text-muted small py-3">등록된 게시글이 없습니다.</li>
                {% endfor %}
            </ul>
        </div>
    </div>
</div>
{% endblock %}

 

💡 naturaltime이 자동으로 해주는 것

{{ post.created_at|naturaltime }} 한 줄을 적으면, 내부적으로 이런 계산을 수행합니다.

  1. 현재 시간(Now)입력된 시간(Created_at)의 차이를 계산합니다.
  2. 그 차이에 따라 적절한 문자열을 리턴합니다.
    • 몇 초 차이: "방금 전 (now)"
    • 몇 분 차이: "3분 전 (3 minutes ago)"
    • 몇 시간 차이: "2시간 전 (2 hours ago)"
    • 하루 이상: "어제 (yesterday)", "3일 전", "1달 전"

4. 화면 수정 2 - 게시글 상세 (boards/board_detail.html)

게시글 상세 화면(boards/board_detail.html)에서 게시글과 댓글 작성 시간에도 적용합니다.

{% extends 'base.html' %}
{% load humanize %} {% block content %}
<span class="text-muted small ms-2">{{ post.created_at|naturaltime }}</span>
<span class="text-muted small ms-2">{{ comment.created_at|naturaltime }}</span>
{% endblock %}

5. 화면 수정 3 - 쪽지함 (accounts/message_list.html)

쪽지함 (accounts/message_list.html)쪽지 수신 시간에도 적용합니다.

{% extends 'base.html' %}
{% load humanize %} {% block content %}
<small class="text-muted">{{ msg.created_at|naturaltime }}</small>
{% endblock %}

6. 테스트

  1. 조회수 방지: 게시글 접속 후 F5를 눌러도 조회수가 그대로인지 확인합니다.
  2. 시간 표시: "방금 전", "5분 전" 등으로 예쁘게 나오는지 확인합니다.