본문 바로가기
개발자모드/혼자공부하는파이썬

[장고#07] 질문 목록과 질문 상세 기능 구현 (ft. 템플릿등록, 화면추가, render 함수사용, URL매핑)

by 요니L 2022. 8. 23.

 

이제 파이보의 핵심 기능을 구현할 것이다. 바로 질문 목록과 질문 상세 기능이다. 우선 /pybo/에 접속하면 질문을 모두 조회할 수 있는 기능을 구현해 보자.

 


질문 목록 조회 구현하기

 

(1단계) Question 모델 데이터 작성일시 최신순으로 조회하기 → pybo/views.py 수정

 

Question 모델을 import해 Question 모델 데이터를 작성한 날짜의 역순으로 조회하기 위해 order_by 함수를 사용했다. 조회한 Question 모델 데이터는 context 변수에 저장했다. context 변수는 이후에 설명할 render 함수가 탬플릿을 HTML로 변환하는 과정에서 사용되는 데이터이다. 

 

# pybo/views.py
from django.shortcuts import render
from django.http import HttpResponse
from .models import Question

# Create your views here.
def index(request):

    question_list = Question.objects.order_by('-create_date')
    context = {'question_list': question_list}
    return HttpResponse("안녕하세요. pybo에 오신 것을 환영합니다!")

order_by 함수는 조회한 데이터를 특정 속성으로 정렬하며, '-create_date'(-) 기호가 작성일시의 역순을 의미한다.

 

 

(2단계) render로 화면 출력하기

 

이제 조회한 Question 모델 데이터를 템플릿 파일을 사용하여 화면에 출력할 수 있는 render함수를 사용해 보자.

pybo/views.py

from django.shortcuts import render

from .models import Question

# Create your views here.
def index(request):
    question_list = Question.objects.order_by('-create_date')
    context = {'question_list': question_list}
    return render(request, 'pybo/question_list.html', context)

render 함수는 context에 있는 Question 모델 데이터 question_list를 pybo/question_list.html 파일에 적용하여 HTML 코드로 변환한다. 그리고 장고에서는 이런 파일을 템플릿이라 부른다. 템플릿은 장고의 태그를 추가로 사용할 수 있는 HTML 파일이라 생각하면 된다. 

 

 

(3단계) 템플릿을 모아 저장할 디렉터리 만들기

템플릿을 만들기 전에 템플릿을 저장할 디렉터리를 루트 디렉터리 바로 밑에 만들자 

(mysite) D:\projects\mysite>mkdir templates

 

 

(4단계) 템플릿 디렉터리 위치 config/settings.py에 등록하기

 

3단계에서 만든 템플릿 디렉터리를 장고 config/setting.py 파일에 등록하자. TEMPLATES 항목을 다음과 같이 수정하자.

# config/setting.py
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / 'templates'],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

DIRS에는 템플릿 디렉터리를 여러 개 등록할 수 있다. 여기서는 1개의 디렉터리를 쓸 것이므로 BASE_DIR / 'templates' 만 등록하자. 현재 BASE_DIR은 D:/projects/mysite 이므로 templates 만 더 붙여서 D:/projects/mysite/templates 를 반환한다.

 

★ 여기서 잠깐!

장고는 DIRS에 설정한 디렉터리 외에도 특정 앱(예를 들어 pybo 앱) 디렉터리 하위에 있는 templates라는 이름의 디렉터리를 자동으로 템플릿 디렉터리로 인식한다. 예를 들어 pybo 앱 디렉터리 밑의 templates 디렉터리는 별다른 설정을 하지 않아도 템플릿 디렉터리로 인식된다. (D:/projects/mysite/templates)

하지만 이 방법을 권장하진 않는다. 왜냐하면 하나의 사이트에서 여러 앱을 사용할 때 여러 앱의 화면을 구성하는 템플릿은 한 디렉터리에 모아 관리하는 편이 여러모로 좋기 때문이다.

 

☞ 공통 템플릿 디렉터리 : D:/projects/mysite/templates

  pybo 앱 템플릿 디렉터리: D:/projects/mysite/templates/pybo

 

 

 

(5단계) 템플릿 파일 만들기

 

question_list.html 템플릿 파일을 mysite/templates/pybo 디렉터리에 생성하자. pybo 디렉터리를 templates 안에 새로 만들어 파일을 추가해야 한다. 그리고 템플릿 파일을 아래와 같이 작성하자.

# D:\projects\mysite\templates\pybo\question_list.html

{% if question_list %}
    <ul>
        {% for question in question_list %}
            <li><a href="/pybo/{{ question.id}}/">{{ question.subject}}</a></li>
        {% endfor %}

    </ul>
{% else %}
    <p>질문이 없습니다.</p>
{% endif %}

{% if question_list %} 이 바로 템플릿 태그이다. 템플릿 태그는 {%%} 로 둘러싸인 문장을 말한다. 

 

 

 

(6단계) 질문 목록이 잘 출력되는지 확인해 보기

 

템플릿 디렉터리를 추가한 상태이므로 장고 개발 서버를 다시 시작해 /pybo/에 접속하자. 장고 개발 서버를 다시 시작하지 않으면 장고가 템플릿 디렉터리를 인식하지 못해 오류가 발생한다. 

 

화면을 보면 이전에 등록한 질문 2건이 보인다. 직접 장고 셸이나 장고 Admin에서 다른 질문도 추가해 보면서 질문 목록이 잘 만들어지는지 테스트해 보기 바란다.

 

 

 


질문 상세 기능 구현하기

 

(1단계) 질문 목록에서 아무 질문이나 눌러보기

 

질문 목록 화면에서 아무 질문이나 눌러보면 아래와 같은 오류 화면이 나타난다.

오류 화면이 나타는 이유는 /pybo/4/에 대한 URL매핑을 추가하지 않았기 때문이다.

 

 

(2단계) pybo/urls.py 열어 URL 매핑 추가하기

 

/pybo/4/의 숨은 의도는 'Question 모델 데이터 중 id=4인 데이터를 조회하라'이다. 이 의도에 맞게 결과 화면을 보여줄 수 있도록 pybo/urls.py파일에서 path('<int:question_id>/', views.detail) URL 매핑을 추가하자.

 

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index),
    path('<int:question_id>/', views.detail)
]

/pybo/4/가 요청되면 이 매핑 규칙에 의해 /pybo/<int:question_id>/가 적용되어 question_id에 4라는 값이 저장되고 views.detail 함수가 실행된다. 

 

 

(3단계) pybo/views.py 열어 화면 추가하기

 

pybo/views.py 파일을 열어 detail 함수를 추가하자. 

 

def detail(request, question_id):
    question = Question.objects.get(id=question_id)
    context = {'question': question}
    return render(request, 'pybo/question_detail.html', context)

추가된 내용은 앞에서 만든 index함수와 크게 다르지 않다. 다만, detail 함수의 매개변수 question_id가 추가된 점이 다르다. 바로 이것이 URL 매핑에 있던 question_id이다. 즉, /pybo/4/ 페이지가 호출되면 최종으로 detail 함수의 매개변수 question_id에 4가 전달된다. 

 

 

(4단계) pybo/question_detail.html 작성하기

 

3단계에서 render함수가 question_detail.html 파일을 사용하고 있으므로 이에 대한 작업도 해야 한다. templates/pybo 디렉터리에 question_detail.html 파일을 작성하자. 

 

# D:\projects\mysite\templates\pybo\question_detail.html

<h1>{{ question.subject }}</h1>

<div>
    {{ question.content }}
</div>

{{ question.subject }}, {{ question.content }} 의 question 객체는 detail 함수에서 render 함수에 전달된 context에 저장한 데이터이다. 

 

 

(5단계) 질문 상세 페이지에 접속해 보기

 

/pybo/4/에 접속해 보자. 그러면 질문 상세 화면이 나타난다!

 

 

 

 


오류 화면 구현하기

지금까지 질문 목록, 질문 상세 기능을 구현했다. 그런데 사용자가 잘못된 주소에 접속하면 어떻게 처리해야 할까?

 

 

(1단계) 잘못된 주소에 접속해 보기

 

/pybo/30/에 접속해 보면 다음과 같은 DoesNotExist 오류 화면이 나온다. 

 

 

(2단계) 페이지가 존재하지 않음(404 페이지) 출력하기

 

존재하지 않는 페이지에 접속하면 오류 대신 404 페이지를 출력하도록 detail 함수를 수정하자. 

Question.objects.get(question_id)를 get_object_or_404(Question, pk=question_id)로 수정하면 된다. 

 

# D:\projects\mysite\pybo\views.py

from django.shortcuts import render, get_object_or_404
from .models import Question

# Create your views here.
def index(request):
    question_list = Question.objects.order_by('-create_date')
    context = {'question_list': question_list}
    return render(request, 'pybo/question_list.html', context)

def detail(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    context = {'question': question}
    return render(request, 'pybo/question_detail.html', context)

 

get_object_or_404 함수는 모델의 기본키를 이용하여 모델 객체 한 건을 반환한다. pk에 해당하는 건이 없으면 오류 대신 404 페이지를 반환한다.

 

 

(3단계) 404 페이지 출력 확인하기

 

/pybo/30/에 접속하면 404페이지가 출력된다.

 

 

☞ 404 페이지가 무엇인가?

웹 브라우저는 HTTP 요청을 하고, 장고는 그 요청에 응답을 한다. 보통의 경우 성공을 의미하는 200 응답 코드가 자동으로 반환된다. 하지만 요청하는 페이지가 없으면 404, 서버에서 오류가 발생하면 500 응답코드를 반환한다.

 


여기까지.

 

댓글