테이블의 모든 글을 목록에 보여주면 안 되는 이유
모델을 만들고 나면 Post.objects.all()을 템플릿에 넘겨 글 목록을 만들 수 있습니다. 하지만 실제 블로그에는 임시·비공개·보호 글과 검색 검토 중인 글이 함께 있습니다. 원문의 단순 조회 예제를 운영 목록에 그대로 쓰면 공개 범위가 달라집니다.
현재 win-j의 첫 화면은 PostListView이며, 발행된 공개 글 중 색인을 허용한 글만 조회합니다. 이 글은 그 조건을 출발점으로 URL, 뷰, 템플릿이 연결되는 과정을 설명합니다. 보호 글 인증이나 관리자 목록 전체를 구현하는 예제는 아닙니다.
요청이 들어오는 순서로 따라가기
브라우저 GET / → myproject/urls.py → blog/urls.py
→ PostListView → 조건에 맞는 Post 조회
→ blog/post_list.html → HTML 응답
models.py는 요청마다 테이블을 만드는 파일이 아닙니다. 모델을 통해 기존 DB를 조회하고 결과를 템플릿에 전달합니다. URLconf는 요청을 받을 뷰를 선택하고, 템플릿은 전달받은 데이터를 표시합니다. 데이터를 이미 저장해 두었더라도 URL이 다른 뷰에 연결되어 있으면 기대한 화면은 나타나지 않습니다.
실제 공개 조건을 남긴 축약 예제
다음은 현재 모델을 사용하는 교육용 목록 뷰입니다. 실제 PostListView의 댓글 수 집계와 사이드바 처리는 생략했지만, 공개 범위·정렬·12개 페이지 구분은 유지했습니다.
from django.views.generic import ListView
from blog.models import Post
class PublicPostList(ListView):
template_name = "blog/post_list.html"
context_object_name = "posts"
paginate_by = 12
queryset = (
Post.objects.filter(
status=Post.PUBLISHED,
visibility="public",
indexing_status=Post.INDEX_INDEX,
)
.select_related("category")
.order_by("-is_pinned", "-created_at")
)
이 코드의 QuerySet을 정의했다고 곧바로 모든 행을 메모리에 가져오는 것은 아닙니다. 평가 시점에 조회가 일어나고 ListView가 페이지 처리를 적용합니다. select_related("category")는 카테고리를 함께 읽기 위한 선택이지 공개 범위를 제한하는 조건은 아닙니다. 기본 조회 동작은 Django QuerySet 안내를 참고할 수 있습니다.
URL과 템플릿에서 이름을 연결한다
현재 실제 첫 화면은 path("", PostListView.as_view(), name="post_list")로 연결됩니다. 위 교육용 클래스로 시험할 때는 별도 학습 URL을 만들어 연결하며 운영 루트에 중복 등록하지 않습니다. 글 상세는 /<slug>/ 형식이고, 구체적인 manager·utility 경로가 먼저 선언되어 있습니다.
목록 템플릿에서 전달받은 posts를 사용하는 최소 예제입니다. 현재 사이트의 전체 카드 디자인을 복제한 코드는 아닙니다.
{% for post in posts %}
<article>
<h2><a href="{{ post.get_absolute_url }}">{{ post.title }}</a></h2>
<p>{{ post.summary }}</p>
<span>{{ post.category.name }}</span>
</article>
{% empty %}
<p>현재 공개된 게시글이 없습니다.</p>
{% endfor %}
템플릿 자동 이스케이프를 유지하면 제목에 들어간 <script> 같은 문자열이 코드로 실행되지 않고 문자로 표시됩니다. 제목이나 요약에 무조건 safe를 붙이지 않습니다. HTML 본문을 렌더링하는 문제는 신뢰할 수 있는 작성 경로와 정제 정책을 포함해 따로 다뤄야 합니다. 상세 URL은 문자열을 직접 이어 붙이기보다 모델의 get_absolute_url()을 사용합니다.
글이 없을 때 확인하는 순서
| 관찰 | 우선 확인 |
|---|---|
| 목록 자체가 404 | URL 등록과 요청 경로 |
| TemplateDoesNotExist | 템플릿 경로·앱 등록·APP_DIRS |
| 빈 목록 문구가 보임 | 발행·공개·색인 조건에 맞는 행 존재 여부 |
| 제목 대신 빈칸 | context 이름과 템플릿 변수 |
| 글은 보이지만 카테고리 조회가 반복 | 관계 조회와 쿼리 수 |
현재 목록에서는 공개 noindex 글도 제외하지만, 공개 발행 상태의 noindex 글은 주소를 직접 열면 본문과 noindex 지시가 나옵니다. 따라서 목록에 없다는 이유만으로 비공개라고 판단하면 안 됩니다. 반대로 임시·비공개·보호 글은 일반 상세 뷰에서 제외됩니다.
검증할 때는 격리한 테스트 DB에 공개 index, 공개 noindex, draft, private, protected 사례를 각각 준비해 목록 포함 여부를 비교합니다. 제목에 HTML처럼 보이는 문자열을 넣어 이스케이프도 확인하면 단순히 “화면이 뜬다”보다 유용한 확인이 됩니다. 실제 운영 글의 상태를 바꾸며 시험할 필요는 없습니다.
모델 관계를 다시 보려면 카테고리 삭제 보호와 migration, 목록과 상세의 공개 정책 차이는 게시글 관리 기록으로 이어서 확인할 수 있습니다.
댓글 0
로그인 없이 궁금한 점이나 의견을 남겨주세요.
아직 댓글이 없습니다. 첫 의견을 남겨주세요.