링크
이 페이지의 내용 정리 위캔입니다.
완성 소스 깃 허브
질문 목록
localhost:8000/pybo
에 접속 시 등록한 질문들을 조회할 수 있도록 구현
- pybo/views.py 수정
# 삭제 from django.http import HttpResponse
# 추가
from django.shortcuts import render
form .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)
- 질문 목록 데이터는
Question.objects.order_by('-create_date')
로 얻을 수 있다.
- order_by는 조회 결과를 정렬하는 함수
order_by(-create_date)
는 작성일시 역순으로 정렬하라는 의미 (-가 없으면 순방향)
- render 함수는 파이썬 데이터를 템플릿에 적용하여 HTML로 반환하는 함수이다.
- 위에서 사용한
return render(request, 'pybo.question_list.html', context)
는
question_list
데이터를 pybo/question_list.html
파일에 적용하여 HTML을 리턴한다.
- 여기서 사용한
pybo/question_list.html
과 같은 파일을 템플릿이라고 부른다.
- 템플릿 파일은 장고에서 사용하는 태그를 사용할 수 있는 HTML파일이다.템플릿 디렉터리
- 템플릿 파일 작성 전에 템플릿 파일을 저장할 디렉터리 생성
config/settings.py
파일의 TEMPLATES 항목에 추가
...
TEMPLATES = [
{
'BACKEND' : 'django.template.backends.django.DjangoTemplates',
# 수정
'DIRS' : [BASE_DIR / 'templates'],
'APP_DIRS' : True,
...
}
]
...
DIRS
는 템플릿 디렉터리를 여러 개 등록할 수 있도록 리스트로 되어있다.
- 파이보는
BASE_DIR / 'templates'
디렉터리만 등록
BASE_DIR
은 ...Django_projects\site2
이므로 추가한 디렉토리 경로는 ...Django_projects\site2\templates
이다.
...Django_projects\site2\templates
디렉터리는 존재하지 않으므로 생성한다.
- ...Django_projects\site>mkdir templates
- 장고는 DIRS에 설정한 디렉터리 외에도 앱 디렉터리 바로 하위에 있는 templates 디렉터리도 템플릿 디렉터리로 이해한다.
- 즉 pybo 앱의 경우 다음의 디렉터리를 생성하면 템플릿 디렉터리로 인식한다. (
...Django_projects\site2\pybo\templates
)
- 모든 앱이 공통으로 사용한 템플릿 디렉터리 -
...Django_projects\site2\templates
- pybo앱만 사용할 템플릿 디렉터리 -
...Django_projects\site2\templates\pybo
템플릿 파일
...Django_projects\site2\templates\pybo
에 question_list.html
파일 저장
- render 함수에서 사용한
pybo/question_list.html
템플릿 파일 작성
{% if question_list %} <!--question_list가 있다면 question_list는 render 함수로 전달받은 질문 목록 데이터이다.-->
<ul>
{% for question in question_list %} <!--for문으로 question_list를 question에 순차적으로 대입-->
<li><a href="/pybo/{{question.id}}/">{{question.subject}}</a></li>
<!--question.id 는 for문으로 대입된 question의 id번호 출력, question.subject는 제목 출력-->
{% endfor %}
</ul>
{% else %}
<p>질문이 없습니다.</p>
{% endif %}
템플릿 태그
- 분기
{% if 조건문1 %}
<p>조건문1에 해당되는 경우</p>
{% elif 조건문2 %}
<p>조건문2에 해당되는 경우</p>
{% else %}
<p>조건문1, 2에 모두 해당되지 않는 경우</p>
{% endif %}
python의 if문과 같다.
항상 {% endif %}
태그로 닫아주어야 한다.
2. 반복
{% for item in list %}
<p>순서: {{ forloop.counter }} </p>
<p>{{ item }}</p>
{% endfor %}
python의 for문과 같다.
항상 {% endif %}
태그로 닫아주어야 한다.
3. 객체 출력
{{ 객체이름 }}
- 객체에 속성이 있는 경우
{{ 객체이름.속성 }}
질문 상세
- 현재 페이지에서 질문의 상세보기를 하면 오류가 발생한다.
http://localhost:8000/pybo/2/
와 같은 페이지에 대한 URL 매핑이 아직 없기 때문이다.urls.py
http://localhost:8000/pybo/2/
이 URL의 의도는 'id 값이 2인 Question을 상세조회한다.'이다.
- 위의 URL이 동작할 수 있도록 urls.py 파일을 수정한다.
- 경로는
...config\urls.py
가 아닌 ...pybo\urls.py
이다.
from django.urls import path
...
urlpatterns = [
path('', views.index),
# 추가
path('<int : quesiton_id>/', views.detail),
# int는 숫자가 매핑됨을 의미한다.
]
path('<int:question_id>/', views.detail)
이라는 URL 매핑을 추가하였다.
- 이제 페이지에서 질문의 상세보기를 하면 위 매핑 룰에 의해
question_id
가 저장되고 view.detail 함수가 실행된다.views.py
- urls.py에서 사용하는 views.detatil 함수를 생성해야 한다.
- views.py 파일에 detail 함수 추가
...
# 추가
def detail(request, question_id):
'''
pybo 내용 출력
'''
question = Question.object.get(id = question_id)
context = {'quesiton' : question}
return context renter(request, 'pybo/question_detail.html', context)
quesiton_detail.html
question_detail.html
템플릿 작성
<h1>{{question.subject}}</h1>
<div>
{{question.content}}
</div>
오류 페이지
http://localhost:8000/pybo/30/
을 요청하면 저장되어있는 id보다 요청값이 더 크기 때문에 오류가 발생한다.
- 존재하지 않는 데이터를 요청할 경우 404페이지(not Found)를 출력하도록 detail 함수 수정
- 경로 :
...pybo\views.py
# 수정
from django.shortcuts import render, get_object_or_404
...
def detail(request, question_id):
...
# 수정
question = get_object_or_404(Question, pk=question_id)
# pk는 Question 모델의 기본키(primary Key)인 id를 의미한다.
...