[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'
현재의 코드를 붙여놓습니다.
모델에서 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---------- #}
이렇게 수정하니 정상 작동합니다. 혹시 저와 같이 드롭다운 메뉴(부트스트랩 템플릿을 이용했습니다.) 를 구현하실 분들은 참고!