728x90

미리보는 프로젝트 완성코드 -->https://github.com/leeceo97/python_community

 

사실 댓글을 구현하는 방식은 아주 많지만 이번에 프로젝트의 목표였던 model, view, templates의 기능을 이용해 보자라는 취지에 맞게 댓글을 구현해 보겠습니다!

 

1. model구성

-boards/models.py

class Comment(models.Model):
    comment = models.TextField()
    author = models.ForeignKey('accounts.User', on_delete=models.CASCADE)
    post = models.ForeignKey('Board', null=True, blank=True, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.comment

    class Meta:
        db_table = 'comment'
        verbose_name = '댓글'
        verbose_name_plural = '댓글'

1:N모델 구성을 위해 ForeignKey로 author(글작성자), post(게시글)을 선언했습니다.

 

2. view, form구성

-boards/forms.py

class CommentForm(forms.ModelForm):
    class Meta:
        model = Comment
        fields = ['comment']

기존의 방식보다는 좀더 편안한 방식인 ModelForm을 사용해보았는데 이건 폼이 알아서 model에 선언되어있는 comment필드에 맞춰 폼형식을 생성해준다는 것입니다. 기존의 복잡하고 귀찮던 코드들이 한껏 간결해진것이 보입니다.

ModelForm같은경우 자세한 설명은 추후 class를 이용한 view구성 프로젝트를 진행할때 제대로 다뤄보겠습니다!

 

-boards/urls.py

from django.urls import path
from .views import board_list, board_write, board_detail, comment_write
urlpatterns = [
    path('list/', board_list, name='board_list'),
    path('write/', board_write, name='board_write'),
    path('detail/<int:pk>/', board_detail, name='board_detail'),
    path('comment_write/<int:board_id>', comment_write, name = "comment_write"),
]

실질적으로 html파일이 존재하지는 않지만 위의 boards/comment_write/<int:board_id>로 값이 보내진다.

 

-boards/views.py

def comment_write(request, board_id):
    comment_write = CommentForm(request.POST)
    user_id = request.session['user']
    user = User.objects.get(pk=user_id)
    if comment_write.is_valid():
        comments = comment_write.save(commit=False)
        comments.post = get_object_or_404(Board, pk=board_id)
        comments.author = user
        comments.save()
    return redirect('board_detail', board_id)

comment_write가 실행되는 경우는 

1. board_detail.html에서 댓글을 입력후 댓글 작성버튼을 눌러

2. boards/comment_write/<int:board_id>로 값이 보내지면 

3. 함수실행 = 댓글저장이 이루어집니다.

 

def board_detail(request, pk):
    board = get_object_or_404(Board, pk=pk)
    comments = CommentForm()
    comment_view = Comment.objects.filter(post=pk)
    return render(request, 'board_detail.html',{'board':board, 'comments':comments, 'comment_view':comment_view})

총 두가지의 값을 반환합니다. 

1. comments --> 댓글작성시 필요한 폼

2. comment_view --> 해당 게시글에 등록되어있는 댓글

-Comment.objects.filter(post=pk)같은 경우 반환받은 게시글의 pk즉 id값에 해당하는 post라는 조건에 맞는 댓글을 가져오는것입니다.

 

3. templates구성

-board_detail.html

{% extends "base.html" %}

{% block contents %}
<div class="row mt-5">
    <div class="col-12">
        <div class="form-group">
            <label for="title">제목</label>
            <input type="text" class="form-control" id="title" value="{{ board.title }}" readonly>
            <label for="contents">내용</label>
            <textarea class="form-control" readonly>{{ board.contents }}</textarea>
            <label for="tags">태그</label>
            <span id="tags" class="form-control">
                {{ board.tags.all|join:"," }}
            </span>

            <form method="POST" action="{% url 'comment_write' board.id %}">
                {% csrf_token %}
                {{ comments }}
                <input type="submit" value="댓글 입력">
            </form>
            {% for comment in comment_view %}
            <hr>
            <p>{{ comment.author }}</p>
            <p>{{ comment.comment }}</p>
            <hr>
            {% endfor %}
        </div>
        <button class="btn btn-primary" onclick="location.href='/boards/list/'">돌아가기</button>
    </div>
</div>
{% endblock %}

위와 같이 템플릿을 구성하면 됩니다.

한가지 처음 다뤄보는 패턴이 form태그에 action이였는데 action은 입력한 url에 데이터를 전송하는겁니다.

그렇기 때문에 comment_write가 수행되어 댓글을 저장하게 됩니다. 

 

4. 마무리 멘트

역시나 이번 챕터또한 새로운 패턴없이 쉽게쉽게 마무리 할수 있었습니다. 그럼 다음은 배포 챕터이므로 마지막까지 화이팅!!! 감사합니다:)

728x90

+ Recent posts