장고 - 업로드된 게시물 연도별로 분류하기

  • 이번 포스트에서는 팀 프로젝트에서 본인이 구현했던 기능 중, 업로드한 게시물을 연도별로 분류했던 방법에 대해 정리해보려고 한다.

ex) extore_project

1. 뷰 작성

  • 경로 : post > views.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    from functools import reduce
    def last_memory(request):
    posts = Post.objects.all()

    posts_year_li = []

    for post in posts:
    posts_year_li.append(post.created.strftime("%Y"))

    posts_year_dict = reduce(lambda dict, ch: dict.update({ch:dict.get(ch,0)+1}) or dict, posts_year_li, {})
    return render(request, 'post/last_memory.html', {'object_dict':posts_year_dict, 'object_list':posts})
  • 코드 설명

    • posts_year_li 라는 빈 리스트를 생성하여 업로드한 게시물 객체의 연도를 순차적으로 추가하였다.
      • 업로드한 게시물 객체의 연도만 표시 : post.created.strftime(“%Y”)
    • 게시물의 연도만 추가한 posts_year_li 리스트에서 reduce 함수를 이용해 연도별 개수를 dictionary 형태로 각각 key 와 value로 변환해주었다.
      • 딕셔너리 형태로 연도별 개수를 각각 key와 value로 설정 : posts_year_dict = reduce(lambda dict, ch: dict.update({ch:dict.get(ch,0)+1}) or dict, posts_year_li, {})
    • posts와 posts_year_dict를 context_data로 render 진행

2. 연도별 게시물을 보여줄 html 작성

  • 경로 : post > templates > post > last_memory.html
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    {% extends 'post-base.html' %}
    {% block extra_script %}
    <script>
    <!-- 특정 연도별 게시물이 있는 위치로 이동하는 함수 작성 -->
    function year_move(year){
    var offset = $(".year-" + year).offset();
    $("html,body").animate({scrollTop : offset.top}, 400);
    }
    </script>
    {% endblock %}
    {% block content %}
    <div id="screen">
    <div style="display:inline-block; width:1200px;">
    <div id="show-year">
    <div id="show-year-inner">
    <p style="margin-bottom:5px; position:relative; left:-13px; color:rgb(130,130,130);">year</p>
    {% if object_dict %}
    <!-- 연도별 업로드한 게시물(posts) 개수 표시 -->
    {% for keys, values in object_dict.items %}
    <div class="show-year" style="height:60px; line-height:60px;">
    <div class="year-line"></div>
    <div class="year-circle year-circle-{{keys}}"></div>
    <!--업로드한 게시물 개수가 1개일 경우-->
    {% ifequal values 1 %}
    <!-- 상기 작성한 year_move(year)함수를 이용하여 클릭한 연도의 게시물 위치로 이동하도록 코드 작성 -->
    <p class="year-move year-move-{{keys}}" onclick="year_move('{{keys}}');">{{keys}}&ensp;<span>{{values}} post</span></p>
    <!--업로드한 게시물 개수가 2개 이상일 경우-->
    {% else %}
    <p class="year-move year-move-{{keys}}" onclick="year_move('{{keys}}')">{{keys}}&ensp;<span>{{values}} posts</span></p>
    {% endifequal %}
    </div>
    {% endfor %}
    {% else %}
    <!--포스트 없는 경우의 div 추가-->
    {% endif %}
    </div>
    </div>
    <!-- 전체 포스트 목록 -->
    <div id="show-posts">
    <!-- 연도별 포스트 -->
    {% for keys, values in object_dict.items %}
    <div class="show-post">
    <p class="year-{{keys}}" style="font-size:30px; text-align:center;">{{keys}}</p>
    <div style="display:inline-block; text-algin:left;">
    {% for object in object_list %}
    <!-- 커스텀 템플릿 태그를 이용(post > templatetags > calc.py) -->
    {% load calc %}
    <!-- 연도별 업로드한 게시물을 분류하는 비교연산자 -->
    {% ifequal object.created|return_year keys %}
    <!--연도별 post 목록-->
    <div class="card" onclick="location.href='{% url 'post:detail' object.id %}';" style="margin: 10px; width: 13rem; float:left; text-align:left;">
    <div class="show-post-image" style="background-image:url({{object.image.url}});"></div>
    <div style="padding:12px 20px;">
    <p class="card-text">{{object.text|truncatechars:9}} <span style="color:rgb(130,130,130); font-size:13px; float:right;">상세보기</span></span></p>
    </div>
    <ul class="list-group list-group-flush">
    <li class="list-group-item">
    <p style="margin:0; display:inline-block; font-size:15px;">{{object.author.last_name}}{{object.author.first_name}}</p>
    <p style="margin:0; float:right; font-size:15px;">{{object.created|date:"n/j D"}}</p>
    </li>
    </ul>
    </div>

    {% endifequal %}
    {% endfor %}
    </div>
    </div>
    {% endfor %}
    </div>

    </div>
    </div>
    {% endblock %}

3. URL 설정

  • 경로 : post > urls.py
    1
    2
    3
    4
    5
    6
    7
    8
    from django.urls import path
    from .views.py import *

    app_name = 'post'

    urlpatterns = [
    path('last_memory/', last_memory, name='last_memory'),
    ]