ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [django] 블로그 카테고리 게시판 만들기(카테고리 별 게시물 리스트, 카테고리 리스트 한 화면에 구현하기)
    Python & Django 2021. 8. 4. 16:00

    보통 블로그나 커뮤니티를 보면 게시물이 카테고리화 되어있고, 카테고리에 들어가면 해당 카테고리의 포스팅들이 나열됩니다. 또한 카테고리 리스트도 같은 화면에 보여주는 경우가 대부분입니다.

     

    이러한 카테고리를 가진 블로그를 만들어보겠습니다.

     

    우선 post 모델에 Category 클래스를 추가합니다. 그리고 Post 클래스 필드로 category 를 추가해줍니다.

    # posts/models.py
    
    from django.db import models
    from django.urls import reverse
    from core import models as core_models
    from users import models as user_models
    
    
    class Category(core_models.TimeStampedModel):
    
        """Category Model Definition"""
    
        name = models.CharField(max_length=20)
    
        def __str__(self):
            return self.name
    
        def get_absolute_url(self):
            return reverse("home")
    
    
    class Post(core_models.TimeStampedModel):
    
        """Post Model Definition"""
    
        category = models.CharField(max_length=30, default="공지사항")
        title = models.CharField(max_length=80)
        writer = models.ForeignKey(user_models.User, on_delete=models.CASCADE, null=True)
        body = models.TextField()
        view_count = models.IntegerField(default=0)
    
        def __str__(self):
            return self.title[:20]

     

     

     

    어드민에서도 관리할 수 있도록 admin.py 에 등록합니다.

    # posts/admin.py
    
    from django.contrib import admin
    from . import models
    
    
    @admin.register(models.Category)
    class CategoryModelAdmin(admin.ModelAdmin):
        pass
    
    
    @admin.register(models.Post)
    class PostModelAdmin(admin.ModelAdmin):
    
        """Post Model Admin Definition"""
    
        list_display = (
            "category",
            "writer",
            "title",
        )
    
        list_filter = ("category",)

     

     

    다음은 뷰 작업입니다.

    def CategoryView(request, category_name):
        category_posts = models.Post.objects.filter(category=category_name)
        categories = models.Category.objects.all()
        return render(
            request,
            "posts/categories.html",
            {
                "category_name": category_name,
                "category_posts": category_posts,
                "categories": categories,
            },
        )

    CategoryView 함수가 받는 인자는 request 와 category_name 입니다. url 에서 주는 category_name 으로 어떤 카테고리를 보여줄 지 결정합니다.

    그리고, 해당 카테고리 링크를 누르면 이에 속하는 posts 를 보여주기 위해 category_posts 라는 변수에 filter 로 post 의 카테고리 값과 category_name 이 일치하는 post 들을 꺼내옵니다.

    그리고 해당 화면에 카테고리 목록도 보여줘야 하기 때문에 모든 카테고리 객체를 받아옵니다.

    이제, render 로 템플릿과 category_name, category_posts, categories 를 전달합니다.

     

     

    다음은 urls.py 입니다.

    from django.urls import path
    from . import views
    
    app_name = "posts"
    
    urlpatterns = [
        ...
        path("category/<str:category_name>/", views.CategoryView, name="category"),
    ]

    category_name 에 따라 서로 다른 페이지로 이동해야 되기 때문에 path converter 를 사용해 category_name 을 넣어줍니다. 이때 "category_name" 은 뷰 함수의 인자인 "category_name" 과 일치해야 합니다.

     

     

     

    이제 템플릿에서 카테고리 목록과 카테고리에 속하는 게시물들을 불러와줍니다.

    {% extends 'base.html' %}
    
    {% block page_title %}{{category_name}}{% endblock page_title %}
    
    {% block content %}
    
    <div>
        <div>
            <h1>소식</h1>
            <ul>
                {% for category in categories %}
                <li><a href="{% url 'posts:category' category.name %}">{{category.name}}</a></li>
                {% endfor %}
            </ul>
        </div>
        
        <div>
            <h1>{{category_name}}</h1>
            {% for post in category_posts %}
                <div>
                    <ul>
                        <li>{{post.title}}</li>
                        <li><a href="{% url 'posts:detail' post.pk %}">보기</a></li>
                    </ul>
                </div>
            {% endfor %}
        </div>
    </div>
    
    {% endblock content %}

    뷰에서 context 로 category_name, category_posts, categories 를 넘겨줬기 때문에 위와 같이 활용할 수 있습니다.

     

    '소식'이라는 게시판에 카테고리 리스트를 만들기 위해 categories 에서 카테고리를 각각 꺼내서 링크를 걸어줍니다. 이때 url 은 앞에서 만든 posts 의 category 로 정해주는데 이때 category.name 을 전달해야 category의 이름에 따라 특정 카테고리를 찾아갈 수 있습니다.

     

    그 아래에는 카테고리에 속해 있는 posts 의 리스트를 보여주기 위해 뷰에서 filter 로 같은 category 를 가지고 있는 posts 를 불러와 category_posts 에 담았습니다.

    이를 활용해, 반복문으로 posts 들을 꺼내주면 post 리스트가 만들어집니다.

     

    이를 활용해 구현한 동아리 홈페이지의 소식 화면 모습입니다.


    추가로 nav 의 url 에서 첫번째 카테고리 화면으로 넘어가도록 구현해보았습니다.

     

    {% load static %}
    <div><a href="{% url 'core:home' %}"><img src="{% static 'img/logo/logo.png' %}" alt=""></a></div>
    <ul>
        <li class="nav-link"><a href="{% url 'core:home' %}">MY BLOG</a></li>
        <li class="nav-link"><a href="{% url 'posts:category' category_name='공지사항' %}">게시글</a></li>
    </ul>

    저는 네비게이션 바에서 '게시글' 버튼을 누르면 카테고리 중 첫번째인 '공지사항' 화면을 보여주고 싶었는데, 인자로 '공지사항'을 어떻게 넘겨줘야 할 지 많이 헤맸습니다.

     

    이런 경우에는 url 을 지정해주고, 뷰에서는 category_name 이라는 인자를 받아야 하기 때문에 위와 같이 작성하면 됩니다. 사실 단순한 거였더라구요..

     

    앞으로 이런 경우에는 뷰에 있는 함수에 넘겨줄 인자가 무엇인지만 확실히 고민해보면 될 것 같습니다.

     


Designed by Tistory.