2019.05.16 장고 댓글 기능 구현하기 함수형 뷰
댓글 기능 구현하기(함수형 뷰에서 구현하기)
모델이 있다고 꼭 그 모델의 뷰가 필요한 것은 아니다.
댓글 같은 경우 그 컨텐츠의 아래에 적히는 것이기 때문에 그 컨텐츠의 뷰에서 처리한다.
폼이 있어야 한다. form.py를 만들거나 템플릿에서 만들어줘야 한다.
한 뷰에서 처리하기(detail 뷰에서 처리하기)
- 모델 구현하기
- form.py 구현하기
- 뷰 구현하기
- 템플릿 구현하기
댓글 기능을 하나의 뷰로 빼서 처리하기
- 모델 구현하기
- form.py구현하기
- 뷰 구현하기
- 템플릿 구현하기
- form 의 action에 view를 연결하기 위해 url을 설정해줘야한다.
- url 연결해주기
- url을 뷰로 연결시켜준다.
모델 구현하기
class Comment(models.Model):
document = models.ForeignKey(Document, on_delete=models.CASCADE, related_name='comments')
author = models.ForeignKey(get_user_model(), on_delete=models.SET_NULL, null=True, blank=True, related_name='comments')
text = models.TextField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
like = models.IntegerField(default=0)
dislike = models.IntegerField(default=0)
def __str__(self):
return (self.author.username if self.author else "무명")+ "의 댓글"
- get_user_model : 커스텀 모델 , 커스텀 USER를 넣거나 없으면 그냥 USER를 받음
- author : models.SET_NULL : 연결된 foreignkey 즉 USER가 삭제되어도 Comment를 null로 바꾸고 남겨놓는다. 단 null=True가 필요하다.
form.py 구현하기
from .models import Document, Comment
class CommentForm(forms.ModelForm):
#text = forms.TextInput(label = '댓글')
class Meta:
model = Comment
fields = ['text']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['text'].label = "댓글"
- text필드를 댓글이라는 문구로 바꾸어 줄 수 있다.
- text = forms.TextInput(label = '댓글') 혹은
- 아래의 def _init_ 을 통해 구현하기
views.py 뷰 구현하기
document_detail 뷰에서 구현할 때
def document_detail(request, document_id):
document = get_object_or_404(Document, pk=document_id)
#만약 post일때만 댓글 입력에 관한 처리를 더한다.
if request.method == "POST":
comment_form = CommentForm(request.POST)
comment_form.instance.author_id = request.user.id
comment_form.instance.document_id = document_id
if comment_form.is_valid():
comment = comment_form.save()
#models.py에서 document의 related_name을 comments로 해놓았다.
comment_form = CommentForm()
comments = document.comments.all()
return render(request, 'board/document_detail.html', {'object':document, "comments":comments, "comment_form":comment_form})
detail에서는 get_object_or_404로 하나만 뽑아내야 하고 따라서 pk키도 필요하다.
- list에서는 get_list_or_404로 전체를 뽑아낸다.
document.comments.all() 아래에 와야지 논리오류가 발생하지 않는다.
comment_form 의 위치에 따라서 글자가 바뀐다.
- comment_form.save 아래에 위치하게 되면 저장된 상태로 그대로 넘어가서 정보가 남아있게 된다.
self.instance = 상속받은 객체 그 자체
댓글 기능 따로 빼서 구현하기
def comment(request, document_id):
if request.method == "POST":
comment_form = CommentForm(request.POST)
comment_form.instance.author_id = request.user.id
comment_form.instance.document_id = document_id
if comment_form.is_valid():
comment = comment_form.save()
return HttpResponseRedirect(reverse_lazy('board:detail', args=[document_id]))
# get_absolute_url을 설정해 놓았을 시(in models)
def get_absolute_url(self):
return reverse('board:detail', args=[self.id])
제일 마지막 문장 return redirect(document)로 대체가능
- 하지만 이렇게 해주면 해당 뷰로 접근하기 위한 url이 필요하게 되고 탬플릿의 form에서 action에 url을 설정해줘야 한다.
- 그리기 위해서 또 urls.py에 url을 연결하여 해당 views로 접근하도록 한다.
- path('comment/int:document_id/', comment, name="comment"),
- 그리고 그 뷰를 실행하고 redirect를 활용하여 detail 페이지로 가도록 구현해준다.
템플릿 구현하기
- document_detail.html
{ % extends 'base.html' % }
{ % block content % }
{{object.title}}
{{object.text}}
{{object.image.url}}
{{object.author.username}}
<form action="{ % url "board:comment" object.id % }" method="POST">
{ % csrf_token % }
{{comment_form.as_p}}
<input type="submit" value="Comment" class="btn btn-outline-primary">
</form>
<table class="table table-striped">
{ % for comment in comments % }
<tr>
<td>{{ comment.text }}</td>
<td>{{ comment.author.username}}</td>
<td>{{ comment.created }}</td>
<td><a href="{ % url 'board:comment_delete' comment.id % }">삭제하기</a></td>
<td><a href="{ % url 'board:comment_update' comment.id % }">수정하기</a></td>
</tr>
{ % endfor % }
</table>
{ % endblock % }
- 만들어 놓은 comment_form을 가지고 온다.
- 댓글 기능을 따로 구현하였다면 위와 같이 form의 action이 필요하고 그렇지 않다면 없어도 된다.
- comments를 돌면서 관련 댓글을 뽑아오는데 이 comments는 detail 뷰에서 받아왔다.
- document = get_object_or_404(Document, pk=document_id) 를 통해 특정 document에 대한 것들만 다 가지고 온다음에
- comments = document.comments.all()를 통해 해당 document의 comment를 모두 가지고 왔다.
- 옛날에 나는 일단 모든 comment를 다 가지고 온 다음에 템플릿 단에서 각 객체들의 id를 비교하여 보여줄 수 있도록 했었고
- 그 다음에는 filter를 통해 구현해보려고 헀었다.
- 하지만 그럴 필요 없이 미리 document를 pk값으로 특정 document를 가지고 오고 그 모든 comment를 템플릿으로 넘겨줌으로서 해결 할 수 있다.
'Django' 카테고리의 다른 글
Django debug tool bar설치하기 (0) | 2019.12.28 |
---|---|
Django 장고 댓글 삭제 및 수정 구현하기 (0) | 2019.12.28 |
Django 장고 페이지 서칭 기능 구현 (0) | 2019.12.28 |
Django 장고 페이징 기능 구현 (0) | 2019.12.28 |
Django 장고 정적파일(STATIC,MEDIA) (0) | 2019.12.28 |