Django에서 카테고리 필터 구현하기

Kangjik Kim·2025년 4월 29일

게시판이나 상품 목록과 같은 페이지에서 카테고리별 필터링은 매우 흔한 요구사항입니다.

오늘은 Django에서 간단하게 카테고리 필터를 구현하는 방법을 알아보겠습니다.

1. 모델 설정

먼저 카테고리를 가진 기본적인 모델을 정의합니다:

class Post(models.Model):
    CATEGORY_CHOICES = [
        ('TECH', '기술'),
        ('LIFE', '일상'),
        ('HOBBY', '취미'),
        ('OTHER', '기타'),
    ]

    title = models.CharField(max_length=200)
    content = models.TextField()
    category = models.CharField(
        max_length=20,
        choices=CATEGORY_CHOICES
    )
    created_at = models.DateTimeField(auto_now_add=True)

2. View 구현

카테고리 필터링을 처리할 View를 작성합니다:

from django.views.generic import TemplateView
from django.shortcuts import redirect

class PostListView(TemplateView):
    template_name = 'posts/list.html'

    def get(self, request, *args, **kwargs):
        # category 파라미터가 없으면 ALL로 리다이렉트
        if 'category' not in request.GET:
            return redirect(f"{request.path}?category=ALL")
        return super().get(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        # 선택된 카테고리 가져오기
        selected_category = self.request.GET.get('category', 'ALL')

        # 게시글 필터링
        posts = Post.objects.all().order_by('-created_at')
        if selected_category != 'ALL':
            posts = posts.filter(category=selected_category)

        context.update({
            'posts': posts,
            'category_choices': Post.CATEGORY_CHOICES,
            'selected_category': selected_category,
        })
        return context

3. 템플릿 구현

카테고리 필터 UI를 구현합니다:

{% extends 'base.html' %}

{% block content %}
    {# 카테고리 필터 버튼 #}
    <div class="category-filter">
        <a href="?category=ALL"
           class="category-btn {% if selected_category == 'ALL' %}active{% endif %}">
            전체
        </a>
        {% for category_code, category_name in category_choices %}
            <a href="?category={{ category_code }}"
               class="category-btn {% if selected_category == category_code %}active{% endif %}">
                {{ category_name }}
            </a>
        {% endfor %}
    </div>

    {# 게시글 목록 #}
    <div class="post-list">
        {% for post in posts %}
            <div class="post-item">
                <h2>{{ post.title }}</h2>
                <p>카테고리: {{ post.get_category_display }}</p>
                <p>작성일: {{ post.created_at|date:"Y-m-d" }}</p>
            </div>
        {% endfor %}
    </div>
{% endblock %}

{% block extra_css %}
<style>
    .category-filter {
        margin: 20px 0;
    }
    .category-btn {
        display: inline-block;
        padding: 8px 16px;
        margin-right: 10px;
        border: 1px solid #ddd;
        border-radius: 4px;
        text-decoration: none;
        color: #333;
    }
    .category-btn.active {
        background-color: #007bff;
        color: white;
        border-color: #007bff;
    }
    .post-item {
        margin-bottom: 20px;
        padding: 15px;
        border: 1px solid #eee;
        border-radius: 4px;
    }
</style>
{% endblock %}

주요 기능

  1. 카테고리 없는 접속 처리:
    • 처음 페이지 접속 시 자동으로 ?category=ALL로 리다이렉트
  2. 카테고리 필터링:
    • 'ALL' 선택 시 모든 게시글 표시
    • 특정 카테고리 선택 시 해당 카테고리의 게시글만 표시
  3. UI/UX:
    • 현재 선택된 카테고리 버튼 강조 표시
    • 깔끔한 버튼 스타일링

확장 가능성

  1. 페이지네이션 추가:
    • 카테고리 필터와 함께 페이지네이션 구현 가능
  2. 다중 필터:
    • 날짜, 태그 등 추가 필터 조건 구현 가능
  3. 정렬 기능:
    • 최신순, 조회순 등 정렬 옵션 추가 가능

이렇게 간단하게 Django에서 카테고리 필터를 구현할 수 있습니다.

0개의 댓글