지난 이야기🌿
7주 차에는 장고(Django)에서 CRUD기능을 구현했다.
8주 차(2021.05.17-2021.05.20)
8주 차에는 프로젝트에 새 앱을 만들어 회원가입, 로그인, 로그아웃 기능을 만들었다. 그리고 모델에 Comment 클래스를 추가해 댓글 기능을 추가했다.
ForeignKey
댓글 기능을 알기 전 ForeignKey에 대해 알아보자. ForeignKey(외래키)란 테이블 필드 중에서 다른 테이블의 행과 식별할 수 있는 키를 의미한다.
=> 테이블과 테이블을 연결하기 위해 사용하는 키
- ForeignKey는 model간의 1:N 관계를 나타낼 때 사용한다(게시글과 댓글 관계).
- 1:N 중에서 N인 쪽 관계를 선언하며, 두 개의 인자를 필요로 한다(대상이 되는 클래스 및 삭제 설정).
장고에서의 사용 예시를 보자.
#models.py 예시
from django.db import models
from django.db.models.deletion import CASCADE
class Post(models.Model):
···
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=CASCADE)
* on_delete를 CASCADE로 설정하면 이와 연결된 모든 N 쪽 데이터를 삭제한다.
표로 나타내면 아래와 같다.
* 외래키 값을 가진 테이블은 부모 테이블(Post), 외래키가 포함된 테이블을 자식 테이블(Comment)이라 한다.
그럼 이제 본격적으로 댓글 달기 기능을 만들어보자!
1. models.py
#main/models.py
from django.db import models
from django.contrib.auth.models import User
from django.db.models.deletion import CASCADE
class Write(models.Model):
title = models.CharField(max_length=50)
contents = models.TextField()
updated_at = models.DateTimeField(auto_now=True)
user = models.ForeignKey(User, on_delete=CASCADE)
def __str__(self):
return self.title
class Comment(models.Model):
post = models.ForeignKey(Write, related_name="comment", on_delete=CASCADE)
user = models.ForeignKey(User,related_name="comment", on_delete=CASCADE)
content = models.TextField(max_length=200)
def __str__(self):
return self.post.title
- user 변수에 models.ForeignKey을 사용해 User 모델에 Write, Comment 모델을 종속
- post 변수에는 Write 모델에 Comment 모델을 종속
- 사용자 또는 게시글이 삭제되면 댓글도 삭제되도록 on_delete=CASCADE 사용
2. forms.py
#main.forms.py
···
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ['content']
···
Meta 클래스에 Comment 모델을 넣고, content 필드를 가져다 쓰도록 설정
3. urls.py - views.py - templates
1) urls.py
#main/urls.py
from django.urls import path
from . import views
app_name="main"
urlpatterns = [
path('', views.index, name='index'),
path('create/', views.create, name='create'),
path('detail/<int:write_id>', views.detail, name='detail'),
path('update/<int:write_id>', views.update, name='update'),
path('delete/<int:write_id>', views.delete, name='delete'),
#추가된 부분
path('create_comment/<int:write_id>', views.create_comment, name='create_comment'),
path('delete_comment/<int:write_id>/<int:comment_id>', views.delete_comment, name='delete_comment'),
]
2) views.py
#main/views.py
from django.shortcuts import get_object_or_404, redirect, render
from .forms import WriteForm, CommentForm
from .models import Write, Comment
from django.contrib.auth.models import User
···
def detail(request, write_id):
user = request.user
my_write = get_object_or_404(Write, pk=write_id)
comment_form = CommentForm()
comments = Comment.objects.filter(post = write_id) #Comment객체에서 post가 write_id인 것들만 가져오기
return render(request, 'detail.html', {'my_write':my_write, 'comment_form': comment_form, 'comments':comments, 'user':user})
···
def create_comment(request, write_id):
if request.method == "POST":
comment = CommentForm(request.POST) #POST 요청으로 넘어온 데이터를 CommentForm 양식에 넣고 comment 변수에 담기
if comment.is_valid: #해당 폼이 유효한 경우 저장하고 detail.html로 돌아가기
form = comment.save(commit=False)
user = request.user
form.user = User.objects.get(id=user.id) #user 필드에 값 추가
form.post = Write.objects.get(id=write_id) #post 필드에 값 추가
form.save()
return redirect("main:detail", write_id)
def delete_comment(request, write_id, comment_id):
my_comment = get_object_or_404(Comment, id=comment_id)
my_comment.delete()
return redirect("main:detail", write_id)
- 게시글 아래에 CommentForm을 띄워주기 위해 views.py의 detail 함수 수정
- create_comment에서 commit=False을 사용해 데이터를 당장 저장시키지 않고 지연
- form에 user, post 정보를 넣고 난 후 저장
*detail.html은 게시글 제목과 내용을 보여주는 페이지다.
3) detail.html
<!-- main/templates/detail.html -->
···
<body>
···
<h2>댓글</h2>
{% if user.is_authenticated %}
<form method="POST" action="{% url 'main:create_comment' my_write.id %}">
{% csrf_token %}
{{comment_form}}
<button type="submit">댓글작성</button>
</form>
{%endif%}
{% for comment in comments %}
{{comment.user}}
{{comment.content}}
<a href="{% url 'main:delete_comment' my_write.id comment.id%}">삭제하기</a>
<br>
{%endfor%}
</body>
</html>
- is_authenticated를 사용해 로그인한 유저만 댓글을 작성할 수 있도록 설정
- views.py detail 함수에서 템플릿 변수로 담아준 comments를 for문으로 출력
댓글이 잘 써지는지 확인해보자!
변수가 점점 많아져서 어질어질하다😵
길고 길었던 8주차 세션 복습도 끝끝
참고자료
'LIKELION 9th' 카테고리의 다른 글
[멋쟁이 사자처럼] 토이프로젝트 아이디어 발표🌊 (0) | 2021.06.03 |
---|---|
[Django] 템플릿 상속 및 css 파일 적용하기(feat. 내비게이션 바) (0) | 2021.05.29 |
[멋쟁이 사자처럼] Django로 블로그 만들기2 (회원가입, 로그인, 로그아웃) (0) | 2021.05.24 |
[멋쟁이 사자처럼] Django로 블로그 만들기(CRUD 기능 구현하기) (0) | 2021.05.16 |
[멋쟁이 사자처럼] 장고 시작하기(단어 수 세기 예제✔) (0) | 2021.05.08 |