Django 점프 투 장고 정리
작성일 : 2021-11-09
문서버전 : 1.0
개요
이 문서는 점프 투 장고 사이트의 장고 튜토리얼 학습 내용을 정리한 내용입니다.
레퍼런스
점프 투 장고 https://wikidocs.net/72242
2-6.데이터 저장
답변 등록하는 기능을 만들어보자.
답변등록
질문 상세 템플릿에 다음처럼 답변을 저장할 수 있는 폼(form)을 추가하자.
> ../projects/mysite/templates/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>
답변 내용 입력할 수 있는 텍스트창, 답변 저장할 수 있는 답변등록 버튼을 추가했다. 답변 저장을 위한 URL은 form 태그의 action 속성에 {% url ‘pybo:answer_create’ question.id %}로 지정했다.
{% csrf_token %}은 보안 관련 항목이다. Form으로 전송한 데이터가 실제 웹 페이지에서 작성한 데이터인지 판단한다. 해커가 다른 방법으로 데이터를 전송할 경우 서버에서 발행한 csrf_token 값과 툴에서 보낸 csrf_token 값의 불일치로 오류를 발생시킨다.
따라서 {% scrf_token %}의 위치는 form 태그 바로 밑에 두어야 한다.
Csrf_token 사용을 위해 CsrfViewMiddleware 미들웨어가 필요하지만 이 미들웨어는 settings.py의 MIDDLEWARE 항목에 디폴트로 추가되어 있으므로 별도의 설정은 필요없다.
> ../projects/mysite/config/settings.py
...
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
...
URL 매핑
위에서 상세 템플릿을 고쳤으니 이제 상세페이지를 요청해보자.
Answer_create 별칭이 없다는 오류가 발생했다. 왜냐하면 질문 상세 템플릿에 {% url ‘pybo:answer_create’ question.id %}과 같은 별칭을 사용했기 때문이다.
> 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'),
]
http://localhost:8000/pybo/answer/create/2/ 와 같은 페이지 요청 시 views.answer_create 함수가 호출된다.
View 함수
위 매핑에서 정의된 views.anwer_create 함수를 아래 추가하자.
> pybo/views.py
from django.shortcuts import render, get_object_or_404, redirect
from django.utils import timezone
from .models import Question
(... 생략 ...)
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)
Answer_create 함수의 매개변수 question_id는 URL 매핑에 의해 값이 전달된다. 만약 http://localhost:8000/pybo/answer/create/2/ 라는 페이지를 요청할 경우 매개변수 question_id에 2가 전달된다.
answer_create 함수의 첫번째 매개변수 request를 통해 답변 등록시 텍스트창에 입력한 내용을 읽는다. request.POST.get(‘content’)는 POST로 전송된 폼(form) 데이터 항목 중 content 값을 의미한다.
답변 생성 위해 question.answer_set.create를 사용했다. Question.answer_set은 질문의 답변을 의미한다. 이렇게 사용할 수 있는 것은 Question과 Answer 모델은 서로 ForeignKey로 연결되어 있기 때문이다.
답변을 저장하는 또 다른 방법이 있다. 이를 방법B라고 하자.
(... 생략 ...)
from .models import Question, Answer
(... 생략 ...)
def answer_create(request, question_id):
"""
pybo 답변등록
"""
question = get_object_or_404(Question, pk=question_id)
answer = Answer(question=question, content=request.POST.get('content'), create_date=timezone.now())
answer.save()
return redirect('pybo:detail', question_id=question.id)
정리해보자.
답변등록 방법A
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)
답변등록 방법B
def answer_create(request, question_id): """ pybo 답변등록 """ question = get_object_or_404(Question, pk=question_id) answer = Answer(question=question, content=request.POST.get('content'), create_date=timezone.now()) answer.save() return redirect('pybo:detail', question_id=question.id) |
방법 A, B의 결과는 동일하다.
Redirect 함수는 페이지 이동을 위한 함수다. 답변 생성 후에는 redirect() 함수를 사용해 질문 상세 화면을 다시 보여주게 했다. detail 별칭은 question_id가 필요하므로 question.id를 인수로 전달했다.
> localhost:8000/pybo/2/
답변 등록은 되지 않는다. 등록된 답변을 표시하는 기능을 템플릿에 추가하지 않은 상태이기 때문이다.
답변 조회
등록된 답변을 질문 상세 화면에 표시하기 위해 다음과 같이 질문 상세 템플릿을 수정해야 한다.
> 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 는 답변의 총 갯수를 의미한다. 위와 같이 수정하고 상세 화면을 호출하면 아래와 같이 나온다.
답변을 확인할 수 있게 되었따.
'Research > Django' 카테고리의 다른 글
[Django] 점프 투 장고 튜토리얼 - 02-8. 부트스트랩 (0) | 2021.11.11 |
---|---|
[Django] 점프 투 장고 튜토리얼 - 02-7. 스태틱 (0) | 2021.11.11 |
[Django] 점프 투 장고 튜토리얼 - 02-5. URL과 네임스페이스 (0) | 2021.11.11 |
[Django] 점프 투 장고 튜토리얼 - 02-4. 조회와 템플릿(template) (0) | 2021.11.11 |
[Django] 점프 투 장고 튜토리얼 - 02-3. 장고 관리자(Admin) (0) | 2021.11.11 |
댓글