장고 Comment 기능 학습
Comment 기능 구현
Comment 기능 적용 방법 중, 현재까지 공부한 방법으로는 크게 2가지로 나뉠 수 있다.
- 특정 앱에 comment 모델 생성하여 구현하는 방법
- comment 앱 추가 생성하여 구현하는 방법
- 여기서는 블로그 프로젝트를 예로 들어, comment 앱을 추가 생성하여 댓글 기능 구현 방법을 정리해보았다.
comment 앱 추가 생성하여 구현하는 방법(블로그 프로젝트)
1. comment 앱 생성
$ python manage.py startapp comment
2. comment 앱 모델 구현
- 경로 : comment > models.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18from django.db import models
from django.contrib.auth import get_user_model
# Create your models here.
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
class Comment(models.Model):
author = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, related_name='my_comments')
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
text = models.CharField(max_length=400)
created = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-created']
3. comment 모델 폼 구현
- 경로 : comment > forms.py
1
2
3
4
5
6
7
8
9
10from django import forms
from .models import Comment
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ['text','content_type','object_id']
widgets = {
'content_type': forms.HiddenInput(),
'object_id':forms.HiddenInput(),
}
4. comment 모델을 관리자페이지에 등록
- 경로 : comment > admin.py
1
2
3
4
5
6from django.contrib import admin
# Register your models here.
from .models import Comment
admin.site.register(Comment)
5. blog 포스트 상세페이지 view 구현
- 경로 : blog > views.py
1
2
3
4
5
6
7
8
9class PostDetail(DetailView):
model = Post
template_name = 'post/post_detail.html'
# 댓글 입력창
def get_context_data(self, **kwargs):
context_data = super().get_context_data(**kwargs)
content_type = ContentType.objects.get_for_model(self.model)
context_data['form'] = CommentForm(initial={'content_type':content_type, 'object_id':self.object.id})
return context_data
6. blog 포스트 상세페이지 html 구현
- 경로 : blog > templates > blog > post_detail.html
1
2
3
4
5
6
7
8
9{% extends 'base.html' %}
{% block content %}
<div>
<!-- comment 앱 > templatetags > comment.py 호출 -->
{% load comment %}
{% show_comment content_type=object object_id=object.id %}
</div>
{% endblock %}
7. 게시물의 comment 목록 반환해주는 페이지 생성
- 경로 : comment > templatetags > comment.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20from django.template.loader import render_to_string
from django.contrib.contenttypes.models import ContentType
from django.template import Library
register = Library()
from comment.forms import CommentForm
from comment.models import Comment
def show_comment(context, content_type, object_id):
# 폼 만들기
content_type = ContentType.objects.get_for_model(content_type)
form = CommentForm(initial={'content_type':content_type, 'object_id':object_id})
# 해당 하는 댓글 목록 뽑기
comments = Comment.objects.filter(content_type=content_type, object_id=object_id).all()
# 템플릿 렌더링
return render_to_string('comment/show_comment.html',{'form':form, 'object_list':comments}, request=context['request'])
8. comment 레이아웃 페이지 생성
- 경로 : comment > templates > comment > show_comment.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14<form action="{% url 'add_comment' %}" method="post">
{% csrf_token %}
{{form.as_p}}
<input type="submit" class="btn btn-primary" value="Write">
</form>
<table class="table table-striped">
{% for object in object_list %}
<tr>
<td>{{object.text}} {% if object.author == user %}<a href="{% url 'delete_comment' object.id %}">[삭제]</a>{% endif %}</td>
<td>{{object.author.username}}</td>
<td>{{object.created}}</td>
</tr>
{% endfor %}
</table>
9. comment 추가/삭제 페이지로 이동하도록 url 설정
- 경로 : comment > urls.py
1
2
3
4
5
6from django.urls import path
from .views import *
urlpatterns = [
path('add_comment/', add_comment, name='add_comment'),
path('delete_comment/<int:pk>/', delete_comment, name='delete_comment'),
]
10. comment 추가/삭제 뷰 코드 구현
- 경로 : comment > views.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29from .forms import CommentForm
from .models import Comment
from django.shortcuts import redirect
from django.contrib import messages
def add_comment(request):
if not request.user.is_anonymous:
comment_form = CommentForm(request.POST)
comment_form.instance.author_id = request.user.id
if comment_form.is_valid():
comment_form.save()
messages.add_message(request, messages.SUCCESS, "댓글을 작성하였습니다.")
else:
messages.add_message(request, messages.WARNING, "Comment Invalid")
else:
messages.add_message(request, messages.WARNING, "댓글은 로그인 사용자만 남길 수 있습니다.")
referer = request.META['HTTP_REFERER']
return redirect(referer)
def delete_comment(request, pk):
comment = Comment.objects.filter(pk=pk)
if comment.exists() and comment[0].author == request.user :
comment.delete()
messages.add_message(request, messages.SUCCESS, "댓글을 삭제하였습니다.")
else:
messages.add_message(request, messages.WARNING, "댓글을 삭제할 수 없습니다.")
referer = request.META['HTTP_REFERER']
return redirect(referer)
Posted