✏️

02-4 질문 목록과 질문 상세 기능 구현하기 본문

ETC./Do it! 점프 투 장고

02-4 질문 목록과 질문 상세 기능 구현하기

콩세 2022. 10. 13. 10:36

파이보의 핵심 기능인 질문 목록과 질문 상세 기능을 구현할 것이다.

/pybo/에 접속하면 질문을 모두 조회할 수 있는 기능을 구현해보자.

 

질문 목록 조회 구현하기

질문 목록 조회를 위해 pybo/views.py 파일을 열어 코드를 수정하자.

 

 

01단계 Question 모델 데이터 작성일시 역순으로 조회하기

 

Question 모델을 임포트해서 Question 모델 데이터를 작성한 날짜의 역순으로 조회하기 위해

order_by 함수를 사용했다.

조회한 Question 모델 데이터는 context 변수에 저장했다.

context 변수는 조금 후에 설명할 render 함수가 템플릿을 HTML로 변환하는 과정에서 사용되는 데이터이다.

order_by 함수는 조회한 데이터를 특정 속성으로 정렬하며,

'-create_date'는 - 기호가 앞에 붙어 있으므로 작성일시의 역순을 의미한다.


02단계 render로 화면 출력하기

 

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

pybo/views.py

render 함수는 context에 있는 Question 모델 데이터 question_list를

pybo/question_list.html 파일에 적용하여 HTML 코드로 변환한다.

 

장고에서는 이런 파일(pybo/question_list.html)을 템플릿 이라 부른다.

템플릿 = 장고의 태그를 추가로 사용할 수 있는 HTML 파일


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

 

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

(루트 디렉터리 = mysite)


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

 

3단계에서 만든 템플릿 디렉터리를 장고 config/setings.py 파일에 등록하자.

DIRS 에는 템플릿 디렉터리를 여러 개 등록할 수 있다.

하지만 지금 개발하는 pybo는 1개의 템플릿 디렉터리를 쓸 것이므로

BASE_DIR / 'templates' 와 같이 1개의 디렉터리만 등록하자.

 

현재 BASE_DIR은 C:/projects/mysite 이므로 templates만 더 붙여

C:/projects/mysite/templates를 반환한다.


05단계 템플릿 파일 만들기

 

3단계에서 만든 템플릿 디렉터리를 참고하여 question_list.html 템플릿 파일을

mysite/templates/pybo 디렉터리에 생성하자.

 

question_list.html 파일에 위와 같이 작성했다.

 

{% if question_list %} 문장을 보면 {% 와 %}로 둘러싸인 문장이 보이는데 이것은 템플릿 태그 이다.

템플릿 태그의 의미를 살펴보면 파이썬 문법과 크게 다르지 않다.

템플릿 태그 의미
{% if question_list %} question_list 가 있다면
{% for question in question_list %} question_list를 순회하며 순차적으로 하나씩 question에 대입
{{ question.id }} for문에 의해 대입된 question 객체의 id번호를 출력
{{ question.subject }} for문에 의해 대입된 question 객체의 제목을 출력

 


 

템플릿 태그의 유형

 

1. 분기

분기 템플렛 태그는 파이썬의 if문과 거의 유사하고,

if문에 끝나는 부분에 {% endif %}를 사용하는 점만 다르다.

{% if 조건문1 %}
    <p>조건문1에 해당되는 경우</p>
{% elif 조건문2 %}
    <p>조건문2에 해당되는 경우</p>
{% else %}
    <p>조건문1, 2에 해당되지 않는 경우</p>
{% endif %}

 

2. 반복

파이썬의 for문과 유사하고, 마지막은 {% endfor %} 로 닫아야 한다.

{% for item in list %}
    <p>순서: {{ forloop.counter }}</p>
    <p>{{ item }}</p>
{% endfor %}

템플릿 for문 안에서는 다음과 같은 forloop 객체를 사용할 수 있다.

forloop 속성 설명
forloop.counter for 문의 순서로 1부터 표시
forloop.counter0 for 문의 순서로 0부터 표시
forloop.first for 문의 첫 번째 순서인 경우 True
forloop.last for 문의 마지막 순서인 경우 True

 

3. 객체 출력

객체를 출력하기 위한 태그의 사용법은 다음과 같다.

{{ 객체 }}

ex) {{ item }}

 

객체에 속성이 있는 경우는 파이썬과 동일한 방법으로 도트(.) 문자를 이용하여 표시하면 된다.

{{ 객체.속성 }}

ex) {{ question.id }}, {{ question.subject }}

 


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

 

템플릿 디렉터리를 추가한 상태이므로 장고 개발 서버를 다시 시작해 /pybo/에 접속하자.

장고 개발서버를 다시 시작하지 않으면 장고가 템플릿 디렉터리를 인식하지 못해 오류가 발생한다.

이전에 만들었던 질문 2개가 보인다.


 

질문 목록 조회 구현하기

 

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

 

위 화면에서 두 질문 중 아무 질문이나 눌러보면 오류 화면이 나타난다.

/pybo/2/ 와 /pybo/3  에 대한 URL 매핑을 추가하지 않았기 때문에 오류가 나타나는 것이다.


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

 

/pybo/2/ => Question 모델 데이터 중 id값이 2인 데이터를 조회하라.

이 의도에 맞게 결과 화면을 보여줄 수 있도록 pybo/urls.py 파일에서

path('<int:question_id>/', views.detail) URL 매핑을 추가하자.

/pybo/2/ 가 요청되면 이 매핑 규칙에 의해 /pybo/<int:question_id>가 적용되어

question_id에 2라는 값이 저장되고 views.detail 함수가 실행된다.


03단계 pybo/views.py 열어 화면 추가하기

 

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

pybo/views.py

전에 만들었던 같은 파일에 만들었던 index 함수와 크게 다르지 않다.

다만 detail 함수의 매개변수 question_id가 추가된 점이 다르다.

이 question_id가 2단계 URL 매핑에 있던 question_id이다.

 

/pybo/2/ 페이지가 호출되면 최종으로 detail 함수의 매개변수 question_id에 2가 전달된다.


04단계 pybo/question_detail.html 작성하기

 

3단계에서 render 함수가 question_detail.htmi 파일을 사용하고 있으므로

이에 대한 작업도 해야한다.

templates/pybo 데릭터리에 question_detail.html 파일을 만든 후 아래 코드를 작성하자.

 

templates/pybo/question_detail.html

{{ question.subject }}와 {{ question.content }}의 question 객체는

detail 함수에서 render 함수에 전달한 context 에 저장한 데이터이다.


05단계 질문 상세 페이지에 접속해 보기

 

/pybo/2/ 에 접속해 보자.

질문 상세 화면이 나타난다.


오류 화면 구현하기

 

01단계 잘못된 주소에 접속해 보기

 

/pybo/30/ 에 접속해 보자.

DoesNotExist 오류 화면이 나온다.

 

question_id가 30인 데이터를 조회하는 Question.object.get(id=30)에서 오류가 발생했기 때문이다.


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

 

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

pybo/views.py

Question.objects.get(id=question_id) 를 get_object_or_404(Question, pk=question_id)로 바꾸었다.

여기서 사용한 pk는 Question 모델의 기본키(Primary Key)에 해당하는 값을 의미한다.

 

get_object or 404 함수는 모델의 기본키를 이용하여 모델 객체 한 건을 반환한다.

pk에 해당하는 건이 없으면 오류 대신 404 페이지를 반환한다.


03단계 404 페이지 출력 확인하기

 

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