장고 거북이반 복습(댓글 기능)

김서영·2022년 10월 24일
0

장고(django)

목록 보기
12/12
post-custom-banner

1. 댓글 모델 작성

class Comment(models.Model):
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateField(auto_now=True)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    # on_delete는 삭제했을때 어떻게 할건지!! CASCADE는 삭제할 때 다 없애겠다.
    article = models.ForeignKey(Article, on_delete=models.CASCADE)
    # 게시글을 삭제하면 게시글에 달린 댓글들도 모두 삭제하겠다.
    
    def __str__(self):  # admin 페이지 tweet앱에서 article object말고 게시글 이름이 뜨게 한다.
        return str(f'{self.user}님이 작성하신 {self.content}')

2. 댓글 모델 어드민 등록

from django.contrib import admin
from tweet.models import Article, Comment

admin.site.register(Article)
admin.site.register(Comment)

3. 댓글 모델 어드민 페이지에서 조작

4. 상세 페이지에서 댓글 보이기

- urls.py

from django.urls import path
from tweet import views

app_name = 'tweet'

urlpatterns = [
    path('', views.index, name='index'),
    path('create_article/', views.create_article, name='create_article'),
    path('<int:article_id>/', views.article_detail, name='article_detail'),
    path('<int:article_id>/update_article/', views.update_article, name='update_article'),
    path('<int:article_id>/delete_article/', views.delete_article, name='delete_article'),
    path('<int:article_id>/create_comment/', views.create_comment, name='create_comment'),
    path('<int:article_id>/delete_comment/<int:comment_id>/', views.delete_comment, name='delete_comment'),
]

- views.py

def create_comment(request, article_id):
    if request.method == 'POST':
        content = request.POST.get('content')
        user = request.user
        Comment.objects.create(content=content, user=user, article_id=article_id)
        return redirect('tweet:article_detail', article_id)

- template

<div>
        <h3>댓글 부분</h3>
        <!-- <div>
        {{ request.user.comment_set.all }}
        내가 작성한 모든 댓글 가져오기
        </div> -->
        {% for comment in article.comment_set.all %}
        <div>
            <div>댓글 작성자 : {{ comment.user }}</div>
            <div>댓글 내용 : {{ comment.content }}</div>
            <br>
        </div>
        {% endfor%}
    </div>

5. 상세 페이지에서 댓글 입력하기

- template

    <div>
        <form action="{% url 'tweet:create_comment' article.id %}" method="post">
        {% csrf_token %}
        <input type="text" name="content" id="content" placeholder="댓글 입력해주세요!">
        <input type="submit">
        </form>
    </div>

6. 상세 페이지에서 본인 댓글 삭제하기

- views.py

def delete_comment(request, article_id, comment_id):
    if request.method == 'POST':
        comment = Comment.objects.get(id=comment_id)
        if comment.user == request.user:
            comment.delete()
            return redirect('tweet:article_detail', article_id)
        else:
            return HttpResponse('권한이 없습니다.')

- template

            {% if comment.user == request.user %}
            <form action="{% url 'tweet:delete_comment' article.id comment.id %}" method="post">
            {% csrf_token %}
            <input type="submit">
            </form>
            {% endif %}

7. 전체 페이지에서 댓글 갯수 표시하기

- count를 사용하는법

{{ article.comment_set.all.count }}

- annotate를 사용하는법

- views.py

articles = Article.objects.annotate(num_comments=Count('comment')) 추가

def index(request):
    articles = Article.objects.all().order_by('-created_at')
    articles = Article.objects.annotate(num_comments=Count('comment'))
    context={
        'articles':articles
    }
    # for article in articles:
    #     print(article)
    #     print(article.content)
    #     print(article.user) -> 값이 username이 나오는 이유는 대표값이 username이기 때문! __str__로 대표값을 지정해주면 그 값으로 나온다!
    #     print(article.user.last_login)
    # user를 users앱에서 foreign key로 가져왔기 때문에 user값와 user.last_login값 등을 가져올 수 있다.
    return render(request, 'index.html', context)
  • template
{{ article.num_comments }}

aggregation 관련 자료 : https://docs.djangoproject.com/en/4.1/topics/db/aggregation/

profile
개발과 지식의 성장을 즐기는 개발자
post-custom-banner

0개의 댓글