[REAL Python – Django] – “Django – Category & Post & Slug & URL 연동(2)”

[REAL Python – Django] – “Django – Category & Post & Slug & URL 연동(2)”

5월 5, 2022

모든 URL에 대한 views.py 작성

from django.db.models import Q
from django.views.generic import ListView, DetailView
from django.http import Http404

from .models import Post, Category


class BasePostListView(ListView):
    '''
    /blog/ 로 들어오면 데이터베이스에 존재하는 모든 게시물이 표시되어야 함
    템플릿의 맨 처음에 "All Posts"
    '''
    model = Post
    ordering = '-pk'
    paginate_by = 9
    template_name = 'blog/base_post_list.html'



class PostByFirstCategoryListView(BasePostListView):
    # 한 포스트의 카테고리의 부모 카테고리의 부모 카테고리(할아버지 카테고리) 가 존재한다 -> 해당 포스트의 할아버지 카테고리 == 1차 카테고리가 됨
    # 3차 카테고리에만 글을 쓸 수 있도록 할 것이므로, 포스트의->카테고리의->부모카테고리의->부모카테고리 == URL 인자인 포스트들 뽑아와야 함
    def get_queryset(self):
        first_category_from_url = self.kwargs['first_category_slug']
        selected_post_list = Post.objects.filter(
            Q(category__parent__parent__name=first_category_from_url) | Q(
                category__parent__parent__slug=first_category_from_url)
            # URL 인자 == 할아버지 카테고리이거나 URL인자 == 할아버지 카테고리의 slug인 포스트들을 가져옴.
        ).distinct()  # 중복 제거
        return selected_post_list


class PostBySecondCategoryListView(BasePostListView):
    # 부모 카테고리이름==URL인자 or 부모카테고리의 슬러그==URL인자 인 포스트들 뽑아오기.
    def get_queryset(self):
        second_category_from_url = self.kwargs['second_category_slug']
        selected_post_list = Post.objects.filter(
            Q(category__parent__slug=second_category_from_url) | Q(category__parent__name=second_category_from_url)
        ).distinct()  # 중복 제거
        return selected_post_list


class PostByThirdCategoryListView(BasePostListView):
    def get_queryset(self):
        third_category_from_url = self.kwargs['third_category_slug']
        selected_post_list = Post.objects.filter(
            Q(category__slug=third_category_from_url) | Q(category__name=third_category_from_url)
        ).distinct()  # 중복 제거
        return selected_post_list


class PostDetailView(DetailView):
    model = Post
    template_name = 'blog/post_detail.html'

현재의 코드를 붙여놓습니다.

URL과 포스트 리스트들이 잘 연동되는 것을 볼 수 있습니다.

모델에서 get_absolute_url 메서드 정의하기

아래는 카테고리 모델의 get_absolute_url 메서드입니다.

    def get_absolute_url(self):
        try:
            if self.parent.parent: # 카테고리의 할아버지 카테고리가 존재한다면,
                return f'/blog/{self.parent.parent.slug}/{self.parent.slug}/{self.slug}/'
            elif self.parent: # 부모 카테고리만 존재한다면,
                return f'/blog/{self.parent.slug}/{self.slug}/'
        except AttributeError:
            return f'/blog/{self.slug}/'

아래는 포스트 모델의 get_absolute_url 메서드입니다.

    def get_absoulute_url(self):
        return f'/blog/{self.category.parent.parent}/{self.category.parent}/{self.category}/{self.pk}/'

위처럼 코드를 작성하면 포스트는 다음의 URL을 가지게 됩니다!

슬러그와 연동되어 잘 동작한 것을 알 수 있습니다. 포스트에 모든 부모 카테고리들도 정상적으로 동작!

발생한 문제 : 카테고리 드롭다운 구현 중 빈 리스트가 생성됨

원했던 것은 부모 카테고리 아래 바로 자식 카테고리 리스트들이 출력되는 것인데, 빈 리스트가 생성됩니다.
                {# ----------categories---------- #}
                <li class="dropdown"><a href="/blog/"><span>Categories</span><i
                        class="bi bi-chevron-down dropdown-indicator"></i></a>

                    {# ----------categories dropdown---------- #}
                    <ul>

                        {% recursetree categories_list %}
                            <li class="dropdown">
                                <a href="{{ node.get_absolute_url }}">
                                    <span>{{ node.name }}</span>
                                    {% if not node.is_leaf_node %}
                                        <i class="bi bi-chevron-down dropdown-indicator"></i>
                                    {% endif %}
                                </a>
                                {% if not node.is_leaf_node %} {# 자식 카테고리가 존재한다면 #}
                                    <ul>
                                        <li class="dropdown"><a
                                                href="{{ children.get_absolute_url }}" >{{ children }}</a></li>
                                        <li><a>hello</a></li>
                                    </ul>
                                {% endif %}
                            </li>
                        {% endrecursetree %}
                    </ul>
                    {# ----------categories dropdown---------- #}

                </li>
                {# ----------categories---------- #}

문제가 발생한 코드인데…

                {# ----------categories---------- #}
                <li class="dropdown"><a href="/blog/"><span>Categories</span><i
                        class="bi bi-chevron-down dropdown-indicator"></i></a>

                    {# ----------categories dropdown---------- #}
                    <ul>

                        {% recursetree categories_list %}
                            <li class="dropdown">
                                <a href="{{ node.get_absolute_url }}">
                                    <span>{{ node.name }}</span>
                                    {% if not node.is_leaf_node %}
                                        <i class="bi bi-chevron-down dropdown-indicator"></i>
                                    {% endif %}
                                </a>
                                {% if not node.is_leaf_node %}
                                    <ul>
                                        <span>{{ children }}</span> {# <li>태그를 로드해 줌. #}
                                    </ul>
                                {% endif %}
                            </li>
                        {% endrecursetree %}
                    </ul>
                    {# ----------categories dropdown---------- #}

                </li>
                {# ----------categories---------- #}

이렇게 수정하니 정상 작동합니다. 혹시 저와 같이 드롭다운 메뉴(부트스트랩 템플릿을 이용했습니다.) 를 구현하실 분들은 참고!

원했던 대로 템플릿이 동작합니다.

Leave A Comment

Avada Programmer

Hello! We are a group of skilled developers and programmers.

Hello! We are a group of skilled developers and programmers.

We have experience in working with different platforms, systems, and devices to create products that are compatible and accessible.