이제 파이보의 핵심 기능을 구현할 것이다. 바로 질문 목록과 질문 상세 기능이다. 우선 /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 응답코드를 반환한다.
여기까지.
'개발자모드 > 혼자공부하는파이썬' 카테고리의 다른 글
[장고#09] 질문에 대한 답변 등록 기능 만들기 (답변저장, 답변조회) (0) | 2022.08.26 |
---|---|
[장고#08] URL 하드코딩 없애는 방법 (ft. URL별칭, 네임스페이스 사용) (1) | 2022.08.25 |
[장고#06] 장고 Admin에서 모델 데이터 추가, 검색기능 추가 (0) | 2022.08.17 |
[장고#05] SQLite 설치, 장고ORM기능, 모델생성, 테이블 생성/저장/조회/수정/삭제 (ft. 장고에 앱등록하기, 장고 쉘shell 실행하기) (0) | 2022.08.16 |
[장고#04] 주소와 화면을 연결하는 URL과 뷰(view) (0) | 2022.08.09 |
댓글