본문 바로가기
Django

(7) 데이터 저장 및 스태틱

by kingyejin 2024. 7. 2.

답변 등록 폼

질문 상세 템플릿에 다음처럼 답변을 저장할 수 있는 폼(form)을 추가하자.

pybo\question_detail.html

<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>

 

답변의 내용을 입력할 수 있는 텍스트창(textarea)과 답변을 저장 할 수 있는 "답변등록" 버튼을 추가했다.   

답변 저장을 위한 URL은 form 태그의 action 속성에 {% url 'pybo:answer_create' question.id %}로 지정했다.


URL 매핑

이제 질문 상세 페이지를 요청해 보자.

pybo/urls.py에 다음과 같은 URL 매핑을 등록하자.

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'),
    path('answer/create/<int:question_id>/', views.answer_create, name='answer_create'),
]


뷰 함수

URL 매핑 규칙에 정의된 views.answer_create 함수를 pybo/views.py 파일에 다음처럼 추가하자.

answer_create 함수의 매개변수 question_id는 URL 매핑에 의해 그 값이 전달된다.

 

그리고 답변을 생성하기 위해 question.answer_set.create 를 사용하였다.  

Question과 Answer 모델은 서로 ForeignKey 로 연결되어 있기때문에 이처럼 사용할 수 있다.

from django.shortcuts import render, get_object_or_404, redirect
from django.utils import timezone
from .models import Question, Answer

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)

def answer_create(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    question.answer_set.create(content=request.POST.get('content'), create_date=timezone.now())
    answer = Answer(question=question, content=request.POST.get('content'), create_date=timezone.now())
    answer.save()
    return redirect('pybo:detail', question_id=question.id)


답변 저장

이렇게 수정한 후 질문 상세 화면을 호출해 보자.

텍스트 창에 아무 값이나 입력하고 답변을 등록해 보자. 

하지만 아직 등록된 답변을 표시하는 기능을 템플릿에 추가하지 않았기 때문에 답변을 등록하더라도 화면에는 아무런 변화가 없을 것이다.


답변 조회

등록된 답변을 질문 상세 화면에 표시하려면 다음과 같이 질문 상세 템플릿을 수정해야 한다.

[파일명: projects\mysite\templates\pybo\question_detail.html]

<h1>{{ question.subject }}</h1>
<div>
    {{ question.content }}
</div>
<h5>{{ question.answer_set.count }}개의 답변이 있습니다.</h5>
<div>
    <ul>
    {% for answer in question.answer_set.all %}
        <li>{{ answer.content }}</li>
    {% endfor %}
    </ul>
</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>

 

중간 부분에 질문에 등록된 답변을 확인할 수 있는 영역을 추가해 주었다. 

question.answer_set.count는 답변의 총 갯수를 의미한다.

 

이렇게 수정하고 다시 질문 상세 화면을 호출하면 다음과 비슷한 화면을 볼 수 있을 것이다.

이제 답변을 저장하고 확인할 수 있게 되었다!


 

스태틱(static) 디렉터리

하지만 좀 더 그럴싸한 화면을 만들기 위해서는 화면에 디자인을 적용해야 한다.

디자인을 적용하기 위해서는 스타일시트(stylesheet, CSS파일)를 사용해야 한다.

 

[파일명: projects\mysite\config\settings.py]

STATICFILES_DIRS이라는 리스트 변수를 추가했다.


스타일시트

이제 style.css 파일을 다음과 같이 신규로 작성하자.

mkdir static

 

[파일명: projects\mysite\static\style.css]

style.css 파일에는 상세화면에 적용할 스타일을 정의했다.

답변 등록시 사용하는 텍스트 창의 넓이를 100%로 하고 "답변등록" 버튼 상단에 10 픽셀의 마진을 설정했다.

textarea {
    width:100%;
}

input[type=submit] {
    margin-top:10px;
}


템플릿에 스타일 적용

이제 작성한 스타일시트 파일을 질문 상세 템플릿에 적용해 보자.

 

[파일명: projects\mysite\templates\pybo\question_detail.html]

{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'style.css' %}">
<h1>{{ question.subject }}</h1>
(... 생략 ...)

 

이제 다음처럼 스타일이 적용된 화면을 볼 수 있을 것이다!

텍스트 창의 넓이가 넓어지고 "답변등록" 버튼 위에 여유공간이 생겼다. 

 

'Django' 카테고리의 다른 글

(9) 템플릿 상속  (0) 2024.07.02
(8) 부트스트랩  (0) 2024.07.02
(6) URL 별칭  (0) 2024.07.02
(5) Pybo 질문 목록과 상세 기능 구현하기  (0) 2024.07.02
(4) 장고 관리자  (1) 2024.07.02