댓글 작성하기
댓글로 모델링되어야 한다. 이때 중요한 점은 각 댓글이 어떤 게시글에 종속적인 댓글인지를 표시해야 한다는 것이다. 외래 키의 필요성이 대두되는 지점이다.
외래키는 models.ForeighKey(참조하는모델이름, on_delete=cascade)
class Comment(models.Model):
comment = models.CharField(max_length=200)
date = models.DateTimeField(auto_now_add=True)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
댓글로부터 사용자로부터 입력을 받아야 하므로 Forms.py에도 댓글을 입력할 폼을 만들어중어야 한다. 폼을 통해 외래키에 해당하는 포스트 아이디를 입력받지는 않으므로 폼의 필드에는 post
칼럼은 포함되지 않는다.
class CommentModelForm(forms.ModelForm):
class Meta:
model = Comment
fields = {'comment', 'image'}
이제 디테일 페이지(detail.html
)에 해당 폼을 넣어주자.
<form action="{% url 'create_comment' Post.id %}"
method="POST"
enctype="multipart/form-data">
{% csrf_token %}
{{ Form}}
<input type="submit" value="댓글 작성하기">
</form>
이 폼에 담긴 정보는 create_comment
이라는 이름rhk 디테일 페이지의 id를 결합한 url 로 넘어갈 것이다. 거기서 댓글이 DB에 저장되는 작업이 이루어진다.
def create_comment(request, post_id):
filled_form = CommentModelForm(request.POST, request.FILES)
if filled_form.is_valid():
finished_form = filled_form.save(commit=False)
finished_form.post = post.objects.get(id=post_id)
finished_form.save()
return redirect('detail', post_id)
폼을 통해 어떤 댓글이 속해 있는 게시글의 ID가 무엇인지 받지 않았으므로 create_comment
에서 해당 필드값의 저장이 이루어져야 한다. 이를 위해선 먼저 모델폼을 생성해서 request.POST에 저장된 데이터를 넣어준 뒤, save(commit=False)
메소드를 호출하여 인스턴스를 생성해주어야 한다. commit=False
는 생성한 인스턴스를 DB에 저장까지 하지는 않겠다는 뜻이다(외래키 값이 아직 정해지지 않았으므로 DB에 저장되면 안된다.)
save()
호출 없이 다음과 같이 실행할 수는 없다.
filled_form.post = post.objects.get(id=post_id)
댓글을 디테일 페이지에 표시되게 하고 싶을 때는 다음의 템플릿 코드를 detail.html에 추가해준다.
{% for comment in Post.comment_set.all %}
<p>{{forloop.counter}}
{{comment}}</p>
{% endfor %}
Post.comment_set.all
은 Post를 참조하는 comment
들의 집합(comment_set) 모두(.all)를 의미한다.