: Question에 author(글쓴이) 속성 추가
pybo/models.py
from django.db import models
from django.contrib.auth.models import User
class Question(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
(... 생략 ...)
django.contrib.auth
앱이 제공하는 사용자 모델. 회원 가입시 데이터 저장에 사용한 모델.ForeignKey로 적용해 선언null=True
🚨 모델 변경 후 반드시 makemigrations
, migrate
를 통해 데이터베이스 변경해야 함.
: Answer에 author(글쓴이) 속성 추가
pybo/models.py
(... 생략 ...)
class Answer(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
(... 생략 ...)
🚨 모델 변경 후 반드시 makemigrations
, migrate
를 통해 데이터베이스 변경해야 함.
: 질문과 답변 저장시 author도 함께 저장해야 함.
pybo/views.py
def answer_create(request, question_id):
(... 생략 ...)
if form.is_valid():
answer = form.save(commit=False)
answer.author = request.user # author 속성에 로그인 계정 저장
(... 생략 ...)
(... 생략 ...)
def question_create(request):
(... 생략 ...)
if form.is_valid():
question = form.save(commit=False)
question.author = request.user # author 속성에 로그인 계정 저장
(... 생략 ...)
request.user
→ 현재 로그인한 계정의 User 모델 객체request.user
가 User 객체가 아닌 AnonymousUser 객체이므로 에러 발생answer.author = request.user
에서 User 대신 AnonymousUser가 대입되어 오류가 발생⇒ request.user
를 사용하는 함수에 @login_required
애너테이션을 사용 해 로그인 필요한 함수로 만듦
pybo/views.py
from django.shortcuts import render, get_object_or_404, redirect
from django.utils import timezone
from .models import Question
from .forms import QuestionForm, AnswerForm
from django.core.paginator import Paginator
from django.contrib.auth.decorators import login_required
(... 생략 ...)
@login_required(login_url='common:login')
def answer_create(request, question_id):
(... 생략 ...)
@login_required(login_url='common:login')
def question_create(request):
(... 생략 ...)
@login_required
어노테이션 사용@login_required
어노테이션이 적용된 함수가 호출되면 자동으로 로그인 화면으로 이동.@login_required
어노테이션은 login_url='common:login'
처럼 로그인 URL을 지정 가능common/login.html
(... 생략 ...)
<form method="post" action="{% url 'common:login' %}">
{% csrf_token %}
<input type="hidden" name="next" value="{{ next }}"> <!-- 로그인 성공후 이동되는 URL -->
{% include "form_errors.html" %}
(... 생략 ...)
pybo/question_detail.html
(... 생략 ...)
<div class="mb-3">
<label for="content" class="form-label">답변내용</label>
<textarea {% if not user.is_authenticated %}disabled{% endif %}
name="content" id="content" class="form-control" rows="10"></textarea>
</div>
<input type="submit" value="답변등록" class="btn btn-primary">
(... 생략 ...)
{% if not user.is_authenticated %}
(로그인 상태가 아닌 경우) textarea 태그에 disabled
속성을 적용 → 로그아웃 시 답변 작성 불가하도록 지정→ 로그아웃 상태에서 답변 등록 클릭 후 로그인 시 발생하는 에러
/answer/create
가 GET 방식으로 호출. (답변 등록시에는 POST가 아닌 경우 HttpResponseNotAllowed
오류를 발생하도록 설정해서 405 에러 발생)해결 :
pybo/views.py 수정
(... 생략 ...)
from django.http import HttpResponseNotAllowed
(... 생략 ...)
@login_required(login_url='common:login')
def answer_create(request, question_id):
question = get_object_or_404(Question, pk=question_id)
if request.method == 'POST':
form = AnswerForm(request.POST)
if form.is_valid():
answer = form.save(commit=False)
answer.author = request.user # author 속성에 로그인 계정 저장
answer.create_date = timezone.now()
answer.question = question
answer.save()
return redirect('pybo:detail', question_id=question.id)
else:
form = AnswerForm()
context = {'question': question, 'form': form}
return render(request, 'pybo/question_detail.html', context)
(... 생략 ...)
question_list.html
(... 생략 ...)
<tr class="text-center table-dark">
<th>번호</th>
<th style="width:50%">제목</th>
<th>글쓴이</th>
<th>작성일시</th>
</tr>
(... 생략 ...)
{% for question in question_list %}
<tr class="text-center">
<td>
<!-- 번호 = 전체건수 - 시작인덱스 - 현재인덱스 + 1 -->
{{ question_list.paginator.count|sub:question_list.start_index|sub:forloop.counter0|add:1 }}
</td>
<td class="text-start">
<a href="{% url 'pybo:detail' question.id %}">{{ question.subject }}</a>
{% if question.answer_set.count > 0 %}
<span class="text-danger small mx-2">{{ question.answer_set.count }}</span>
{% endif %}
</td>
<td>{{ question.author.username }}</td> <!-- 글쓴이 추가 -->
<td>{{ question.create_date }}</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td colspan="4">질문이 없습니다.</td>
</tr>
(... 생략 ...)
<td>{{ question.author.username }}</td>
→ 질문 글쓴이 표시<td colspan="4">질문이 없습니다.</td>
→ 테이블 항목 개수 3에서 4로 증가question_detail.html
(... 생략 ...)
<!-- 질문 -->
<h2 class="border-bottom py-2">{{ question.subject }}</h2>
<div class="card-body">
<div class="card-text" style="white-space: pre-line;">{{ question.content }}</div>
<div class="d-flex justify-content-end">
<div class="badge bg-light text-dark p-2 text-start">
<div class="mb-2">{{ question.author.username }}</div>
<div>{{ question.create_date }}</div>
</div>
</div>
</div>
(... 생략 ...)
<!-- 답변 -->
<h5 class="border-bottom my-3 py-2">{{question.answer_set.count}}개의 답변이 있습니다.</h5>
{% for answer in question.answer_set.all %}
<div class="card-body">
<div class="card-text" style="white-space: pre-line;">{{ answer.content }}</div>
<div class="d-flex justify-content-end">
<div class="badge bg-light text-dark p-2 text-start">
<div class="mb-2">{{ answer.author.username }}</div>
<div>{{ answer.create_date }}</div>
</div>
</div>
</div>
(... 생략 ...)