최근 등록된 질문을 가장 먼저 출력
데이터가 등록된 날짜 역순으로 조회
from .models import Question
def index(request):
# pybo 목록 출력
question_list = Question.objects.order_by('-create_date')
context = {'question_list' : question_list}render로 화면 출력
render 함수는 모델 데이터를 HTML 코드로 변환하여 템플릿에 적용한다. 템플릿은 장고의 태그를 사용할 수 있는 HTML 파일이다.
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)템플릿 디렉토리 생성
TEMPLATES = [
{
...
'DIRS': [BASE_DIR / 'templates'],
...
}
]템플릿 생성
{% if question_list %}
<ul>
{% for question in question_list %}
<li><a href="/pybo/{{ question.id }}/">{{ question.subject }}</a></li>
{% endfor %}
</ul>
{% eles %}
<p>질문이 있습니다.</p>
{% endif %}화면 출력 확인
질문 목록에서 각 질문은 링크가 있다. 이 링크를 따라가면 아직 URL 매핑이 되어있지 않아 페이지를 찾을 수 없다는 오류 페이지가 출력된다.
따라서 각 질문 id에 대한 URL 매핑과 화면을 추가해야한다.
URL 매핑 추가
from django.urls import path
from . import views
urlpatterns = [
path('', views.index),
path('<int:question_id>/', view.detail),
]view.detail 함수 추가
...
def detail(request, question_id):
# pybo 질문 내용 출력
question = Question.objects.get(id=question_id)
context = {'question': question}
return render(request, 'pybo/question_detail.html', context)질문 상세를 표시할 템플릿 생성
<h1>{{ question.subject }}</h1>
<div>
{{ question.content }}
</div>화면 확인
사용자가 잘못된 URL로 접속하면 django의 개발 서버는 아래와 같은 페이지를 표시한다.
하지만 DB 쿼리 결과가 없다는 오류 페이지보다는 페이지가 없다고 표시하는 것이 좀더 직관적이기 때문에 쿼리 오류 대신 404 페이지를 대신 출력하도록 변경
detail 함수를 수정
def detail(request, question_id):
# pybo 질문 내용 출력
question = get_object_or_404(Question, pk=question_id)
context = {'question': question}
return render(request, 'pybo/question_detail.html', context)404 페이지 출력 확인
URL 하드 코딩은 URL이 변경될 경우 이전에 작성한 URL을 일일히 수정해줘야 하는 불편함이 있다. 예를 들어 질문 상세 페이지의 URL이 pybo/2이지만 이 URL이 언제든 pybo/question/2나 pybo/2/question으로 바뀔 수 있고 이 때마다 href를 수정해야 할 수 있다. 이를 해결하기 위해 URL에 실제 주소를 사용하는 대신 별칭을 사용해야 한다.
URL 별칭은 urls.py에서 name 속성을 사용하면 된다.
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('<int:question_id>/', views.detail, name='detail'),
]{% if question_list %}
<ul>
{% for question in question_list %}
<li><a href="{% url 'detail' question.id %}">{{ question.subject }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>질문이 있습니다.</p>
{% endif %}프로젝트에 여러 앱이 있을 때 별칭이 중복 가능성이 있다. 따라서 네임스페이스를 사용하면 앱이 관리하는 독립적인 공간에서 별칭을 관리할 수 있다.
Namespace 추가
Namespace는 urls.py에 app_name 변수를 사용하는 것만으로 간단히 생성가능
from django.urls import path
from . import views
app_name = 'pybo'
urlpatterns = [
path('', views.index, name='index'),
path('<int:question_id>/', views.detail, name='detail'),
]Namespace 적용후 테스트
템플릿에 namespace 적용
{% if question_list %}
<ul>
{% for question in question_list %}
<li><a href="{% url 'pybo:detail' question.id %}">{{ question.subject }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>질문이 있습니다.</p>
{% endif %}질문 상세 페이지에 답변을 등록하도록 답변 등록 버튼 추가
<h1>{{ question.subject }}</h1>
<div>
{{ question.content }}
</div>
<form action="{% url 'pybo:answer_create' question.id %}" method="post">
{% csrf_token %}
<textarea name="content" id="content" rows="15"></textarea>
<input type="submit" value="답변 등록">
</form>URL 매핑
...
urlpatterns = [
path('', views.index, name='index'),
path('<int:question_id>/', views.detail, name='detail'),
path('answer/create/<int:quetion_id>/', views.answer_create, name="answer_create"),
]answer_create 함수 추가
...
from django.utils import timezone
...
def answer_create(request, question_id):
# pybo 답변 등록
question = get_object_or_404(Question, pk=question_id)
question.answer_set.create(content=request.POST.get('content'), create_date=timezone.now())답변 등록 후 질문 상세 페이지로 이동하도록 수정
from django.shortcuts import render, get_object_or_404, redirect
...
def answer_create(request, question_id):
# pybo 답변 등록
question = get_object_or_404(Question, pk=question_id)
question.answer_set.create(content=request.POST.get('content'), create_date=timezone.now())
return redirect('pybo:detail', question_id=question.id)등록된 답변 표시
<h5>{{ question.answer_set.count }}개의 답변이 있습니다.</h5>
<div>
<ul>
{% for answer in question.answer_set.all %}
<li>{{ answer.content }}</li>
{% endfor %}
</ul>
</div>답변 확인
Django 앱에 CSS를 적용하기 위해서 프로젝트 디렉토리에 static 디렉토리를 생성하고 그곳에 CSS 파일을 저장해야한다. 그리고 settings.py에 STATICFILES_DIRS에 static 디렉토리 경로를 추가해야 한다.
static 디렉토리는 앱 디렉토리 하위에 만들면 django가 자동으로 인식한다. 하지만 프로젝트 관리가 불편해질 수 있다.
static 디렉토리 생성
(django_projects) sleepyowl ~/Study/django_projects/test_site
mkdir static
config/settings.py
...
STATIC_URL = 'static/'
STATICFILES_DIRS = [
BASE_DIR / 'static',
]
...
style.css
textarea {
width:100%;
}
input[type=submit] {
margin-top:10px;
}
template/pybo/question_detail.html
<!--css load-->
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'style.css' %}">
CSS 적용된 페이지 확인