AI웹 개발자 과정 공부 (팀스파르타)/Django (장고)

24.04.26_TIL (Django Model Relationship (1:N) 댓글 구현 )

티아(tia) 2024. 4. 26. 20:36
728x90

 

++ 장고 공식 문서는 항상 확인하기 

https://docs.djangoproject.com/en/4.2/

 

 

 

1.  댓글을 구현해보자.

 

  •  my_first_pjt 에 models.py 에 추가해준다.
class Comment(models.Model):
    article = models.ForeignKey(Article, on_delete=models.CASCADE)
    content = models.CharField(max_length=255)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.content

 

  • python manage.py makemigrations 를 진행해준다.
  • python manage.py migrate 도 해준다.

 

 

 

 

  • article_id 값이 없어서 실행하게 되면 에러가 난다.
  • article 에서는 댓글을 모르기 때문에 역참조를 하여 댓글을 게시글에서 조회할 수 있게 한다.
  • 장고에는 매니저가 있어서 이런것을 다 자동으로 해주는 것이 있다.
  • 매니저의 이름은 comments 로 바꾸어준다. - articles 의 models.py 에서 수정하기
class Comment(models.Model):
  article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name="comments")
  content = models.CharField(max_length=120)
  created_at = models.DateTimeField(auto_now_add=True)
  updated_at = models.DateTimeField(auto_now=True)

  def __str__(self):
    return self.content

 

  • 다시 python manage.py makemigrations 를 진행해준다.
  • python manage.py migrate 도 해준다.

 

 

 

 

 

 

 

 

2.  댓글 로직 작성

  • accounts 의 urls.py 수정하기
path("<int:pk>/comments/", views.comments_create, name="comments_create"),

 

  • accounts 의 views.py 수정하기 댓글을 get 방식이 필요없
from .forms import ArticleForm, CommentForm

...

def detail(request, pk):
  article = get_object_or_404(Article, pk=pk)
  comment_form = CommentForm()
  context = { 
    "article": article,
    "comment_form" : comment_form,
  }
  return render(request, "articles/detail.html", context)

...

@require_POST
def comment_create(request, pk):
    article = get_object_or_404(Article, pk=pk)
    form = CommentForm(request.POST)
    if form.is_valid():
        comment = form.save(commit=False)
        comment.article = article
        comment.save()
    return redirect("articles:detail", article.pk)

 

 

  • form 을 생성해야하기 때문에 forms.py 부터 추가해준다.
from django import forms
from articles.models import Article, Comment


class ArticleForm(forms.ModelForm):
    class Meta:
        model = Article
        fields = "__all__" # 모든 필드를 다 가져와서 모델로 만들어줘
        # exclude = ["title"] # 대신 그 중에 타이틀만 빼주고 (제외)

class CommentForm(forms.ModelForm):
    class Meta:
        model = Comment
        fields = "__all__"
        exclude = ("article",)

 

 

  • base.html 을 바꾸어준다.
  <br>
  <hr>
  <h3>댓글</h3>
<form action="{% url 'articles:comment_create' article.pk %}" method="POST">
    {% csrf_token %}
    {{ comment_form.as_p }}
    <input type="submit" value="댓글작성">
</form>

 

 

 

 

 

 

 

 

 

 

3.  댓글을 게시글에 보이게 만들자.

  • accounts 의 views.py 수정하기
def detail(request, pk):
  article = get_object_or_404(Article, pk=pk)
  comment_form = CommentForm()
  comments = article.comments.all()
  context = { 
    "article": article,
    "comment_form" : comment_form,
    "comments" : comments
  }
  return render(request, "articles/detail.html", context)

 

  • base.html 을 바꾸어준다.
<ul>
    {% for comment in comments %}
        <li>
            <p>{{ comment.content }}</p>
        </li>
    {% endfor %}
</ul>

 

  •  시간을 보여주고 싶으면 이렇게 바꾼다.
<ul>
    {% for comment in comments %}
        <li>
            <p>{{ comment.content }} | {{ comment.created_at }}</p>
        </li>
    {% endfor %}
</ul>

 

 

  • 댓글을 최신순으로 정렬하자.
comments = article.comments.all().order_by("-pk")

 

 

 

 

 

 

 

 

 

4.  댓글 삭제 기능 만들어보기

 

  • articles 의 urls.py 에서 path를 만들어준다.
path(
        "<int:pk>/comments/<int:comment_pk>/delete/",
        views.comment_delete,
        name="comment_delete",
    ),

 

 

  • articles 의 views.py 에 추가해준다.
from .models import Article, Comment

...

@require_POST
def comment_delete(request, pk, comment_pk):
    comment = get_object_or_404(Comment, pk=comment_pk)
    comment.delete()
    return redirect("articles:article_detail", pk)

 

 

  • articles 의 tempates에 detail.html 을 바꾸준다.
{% extends "base.html" %}

{% block content %}

    <h2>글 상세 페이지</h2>
    <p>제목: {{ article.title }}</p>

    {% if article.image %}
        <img src="{{ article.image.url }}">
    {% endif %}

    <p>내용: {{ article.content }}</p>
    <p>작성일시: {{ article.created_at }}</p>
    <p>수정일시: {{ article.updated_at }}</p>

    <a href="{% url 'articles:articles' %}">목록보기</a>
    <a href="{% url 'articles:update' article.pk %}">
        <button>수정하기</button>
    </a>

    <form action="{% url 'articles:delete' article.pk %}" method="POST">
        {% csrf_token %}
        <input type="submit" value="삭제">
    </form>

    <br>
    <hr>
    <h3>댓글 {{ comment|length }}개</h3>
    <form action="{% url "articles:comment_create" article.pk %}" method="POST">
        {% csrf_token %}
        {{ comment_form.as_p }}
        <input type="submit" value="댓글작성">
    </form>

    {% for comment in comments %}
    <ul>
        <li>{{ comment.content }}</li>
        <form action="{% url "articles:comment_delete" article.pk comment.pk%}" method="POST">
            {% csrf_token %}
            <input type="submit" value="삭제">
        </form>
    </ul>
    {% endfor %}

{% endblock content %}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형