본문 바로가기

Django/Django 기초

[Django] 2 - 4. 조회와 템플릿

이전 포스트

 

[Django] 1. 개발 환경 설정 https://wroni.tistory.com/4

[Django] 2 - 1. URL과 View https://wroni.tistory.com/5

[Django] 2 - 2. 모델 https://wroni.tistory.com/6

[Django] 2 - 3. 장고 관리자 https://wroni.tistory.com/7


2 - 4. 조회와 템플릿

 

1. 질문 목록

 

이제 로컬 호스트에 /pybo를 요청하면 질문들을 조회할 수 있도록 할 것이다.

 

웹 서버를 구동시키면 저번에 만들어 놓은 "안녕하세요 pybo에 잘 오셨습니다."가 뜨고 있다.

 

이제 질문 목록이 뜨도록 pybo\views.py 파일에 index 함수를 변경하자

 

파일 : C:\projects\mysite\pybo\views.py

from django.shortcuts import render
from .models import Question

def index(request):
    """
    pybo 목록 출력
    """
    question_list = Question.objects.order_by('-create_date')
    context = {'question_list': question_list}
    return render(request, 'pybo/question_list.html', context)

 

* pycharm 캡쳐 상에는 index 함수에 question_list = Question.objects.order_by('-create_data')로 되어 있는데

  data가 아니라 date다! 오류 뜨고나서야 알았다,,, 오타 주의하자(본인은 date를 data로 쓰는 실수를 자주 범하고 있다... 오타 주의)

 

질문 목록 데이터는 Question.objects.oreder_by('-create_date')로 얻을 수 있으며, order_by로 작성일시 역순으로 정렬하고 있다. -가 없으면 순방향, -가 붙어있으면 역방향이다. render 함수는 파이썬 데이터를 템플릿에 적용한 HTML을 반환하는 함수이다. 

 

 

2. 템플릿 디렉터리

 

render 함수로 'pybo/question_list.html'을 반환하기로 했으니, 이제 해당 디렉터리에 html을 만들어야 할 순서다.

템플릿 파일을 생성하기 전에 템플릿 파일을 저장할 디렉터리를 만들자.

먼저 템플릿을 저장할 디렉터리를 config/settings.py 파일에 TEMPLATES 항목에 추가해야 한다.

 

파일 : C"\projects\mysite\config\settings.py

 

'DIRS' 부분에 [BASE_DIR / 'templates'], 를 추가해준다.

 

DIRS 템플릿 디렉터리를 여러 개 등록할 수 있도록 리스트로 되어 있다.

BASE_DIR / 'templates' 에서 BASE_DIR은 C:\projects\mysite이므로 추가한 디렉터리의 전체 경로는 다음과 같다

 

C:\projects\mysite\templates

 

해당 디렉터리가 없으므로 명령 프롬프트에서 생성하자

 

 

장고는 DIRS에 설정한 디렉터리 이외에도 앱 디렉터리 바로 하위에 있는 templates 디렉터리도 템플릿 디렉터리로 인식한다

 

 

C:\projects\mysite\templates\pybo

 

이제 해당 디렉터리를 사용할 것이다. 공통으로 사용하는 템플릿은 templates에 저장할 것이다.

 

 

3. 템플릿 파일

 

이제 드디어 템플릿 파일을 만들 것이다. index 함수에서 render 한 html 파일은 pybo\question_list.html이었다.

 

C:\projects\mysite\templates\pybo\question_list.html

 

파일 : C\projects\mysite\templates\pybo\question_list.html

{% if question_list %}	# question_list가 있으면
    <ul>
    {% for question in question_list %}	  # question_list for loop가 돌고
        <li><a href="/pybo/{{ question.id }}/">{{ question.subject }}</a></li>	# 질문 id, 제목 출력
    {% endfor %}	# for loop문 끝내는 선언
    </ul>
{% else %}	# question_list가 없으면
    <p>질문이 없습니다.</p>	# 질문 없다고 출력
{% endif %}	# if문 끝내는 선언

 

Jinja template 문법을 알고 있으면 편하다. 잘 모르겠다면 주석을 참고하면 된다.

주의할 점은 for loop문 끝내려면 {% endfor %}를 선언해야 하고, if문 끝내려면 {% endif %}를 선언해야 한다.

 

 

4. 템플릿 태그

템플릿 문법을 간단하게 보자면,

 

forloop

forloop 속성 설명
forloop.counter 루프내의 순서로 1부터 표시
forlop.counter() 루프내의 순서로 0부터 표시
forloop.first 루프의 첫번째 순서인 경우 True
forloop.last 루프의 마지막 순서인 경우 True

 

객체

객체 예시
{{ 객체 }} {{ item }}
{{ 객체.속성 }} {{ question.id }}
{{ question.subject }}

 

이제 테스트해보자. /pybo 화면이 어떻게 뜰까

 

 

초반에 작성했던 Question 제목이 잘 조회되고 있다.

 

 

5. 질문 상세

 

질문 목록 중 한 개를 클릭해보자.

 

 

엥 404가 뜬다. 하긴 URL 연결을 안 했으니 당연하다.

 

질문을 클릭한 후 링크를 보면 http://localhost:8000/pybo/2/ 이다. URL의 의도는 id가 2인 Question을 상세 조회하는 것이다.

그렇다면, urls.py로 가서 코드를 수정하자.

 

파일 : C:\projects\mysite\pybo\urls.py

path('<int:question_id>/', views.detail),

 

해당 코드를 추가해준다. 코드는 question_id를 int로 받고, views.detail 함수가 실행된다는 뜻이다. 

 

이제 views.py에 가서 detail 함수를 생성해야 한다.

 

파일 : C:\projects\mysite\pybo\views.py

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

 

해당 코드를 입력하면 detail 함수 호출시 request와 question_id 매개변수로 전달된다. 
question_id에는 URL 매핑 때 저장된 question_id가 전달된다.

이제 http://localhost:8000/pybo/2 페이지를 요청하면 detail 함수의 question_id에는 2라는 값이 전달된다. 

 

detail 함수도 작성하였고, 이제 question_detail.html을 작성하자.

 

파일 : C:\projects\mysite\templates\pybo\question_detail.html

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

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

 

앞에서 설명한 것처럼, 해당 코드는 제목과 내용을 출력하고 있다.

subject는 h1 태크로 크게 나타내고, content는 div 태그로 작게 나타내고 있다.

 

http://localhost:8000/pybo/2 페이지를 요청해보자

 

잘 나오고 있다.

 

 

6. 오류 페이지

id가 30인 질문 페이지를 요청해보자. http://localhost:8000/pybo/30/ 요청하자.

 

 

오류 메세지를 보면 /pybo/30/이 존재하지 않는다고 뜨고 있다. 이 때 브라우저는 500 오류코드를 전달한다.

 

없는 데이터를 요청할 경우는 500 오류 페이지 보다 404 페이지를 리턴하는 것이 좋다.

 

/pybo/30/과 같이 없는 데이터를 요청할 때 404가 뜨도록 detail 함수를 수정하자.

 

파일 : C:\projects\mysite\pybo\views.py

from django.shortcuts import render, get_object_or_404 # get_object_or_404 추가

def detail(request, question_id):
	...
    # 수정할 내용
	question = get_object_or_404(Question, pk=question_id)
    ...

 

import 부분에 get_object_or_404 추가해주고, detail 함수 안에 question 객체를 get_object_or_404로 수정한다.

기본키는 question_id를 나타낸다.

 

이제 다시 /pybo/30 페이지를 요청해보자

 

 

원하는대로 404 오류 페이지가 뜬다.

 


※ 본 내용은 django 공부 기록이며, 점프 투 장고를 참고하였습니다.

https://wikidocs.net/book/4223

 

점프 투 장고

**점프 투 장고 오프라인 책 출간 !! (2020.12)** * [책 구입 안내](https://wikidocs.net/105844)

wikidocs.net

 

'Django > Django 기초' 카테고리의 다른 글

[Django] 2 - 7. 스태틱  (0) 2021.11.29
[Django] 2 - 5. URL과 네임스페이스, 2 - 6. 데이터 저장  (0) 2021.11.26
[Django] 2 - 3. 장고 관리자  (0) 2021.11.24
[Django] 2 - 2. 모델  (0) 2021.11.24
[Django] 2 - 1. URL과 View  (0) 2021.11.24