이번에는 로그인 후 트윗을 올리고 그 트윗을 선택하면 댓글을 달 수 있는 상세 페이지가 보이게 만드려고 한다.
우선 model.Model 을 상속받은 TweetModel을 model.py에 추가해준다.
class TweetModel(models.Model):
class Meta:
db_table = "tweet"
author = models.ForeignKey(UserModel, on_delete=models.CASCADE)
content = models.CharField(max_length=256)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
created_at과 updated_at은 auto 이니 우리가 채워줄 것은 author과 content 이다.
tweet/home.html 에서 tweet을 받아 현재 로그인한 사용자를 author 로 넘겨주어 tweet 데이터베이스에 저장한 뒤, iterater로 받아 시간의 역순으로 출력해줄 것이다.
/tweet 으로 접속하기 위해서는 우선 사용자가 인증을 받았는지 - 로그인이 되었는지 - 검사해야 하므로 is_authenticated 를 통해 인증 검사를 한다
def home(request):
# 로그인이 된 사람만
user = request.user.is_authenticated
if user:
return redirect('/tweet')
else:
return redirect('/sign-in')
로그인이 된 사용자면 /tweet 으로 보내주고 아니라면 로그인 페이지로 보내준다. 이후 tweet 페이지에서는 로그인이 된 사용자일 시 home.html 페이지를 렌더링하고 all_tweet 에 tweet 데이터베이스에 있는 모든 트윗을 시간의 역순으로 담아준다.
view.py
def tweet(request):
if request.method == "GET":
user = request.user.is_authenticated
if not user:
return redirect('/sign-in')
else:
all_tweet = TweetModel.objects.all().order_by('-created_at')
return render(request, 'tweet/home.html', {'tweet' : all_tweet})
home.html 에는 tweet 에 all_tweet을 담아 보내고, home.html 에서는 반복문을 통해 all_tweet 을 열로 출력한다.
home.html
<div class="row">
{% for tw in tweet %}
<div class="col-md-12 mb-2">
<div class="card">
<div class="card-body">
{% if tw.author == user %}
<div style="text-align: right">
<a href="/tweet/delete/{{ tw.id }}">
<span class="badge rounded-pill bg-danger">삭제</span>
</a>
</div>
{% endif %}
<div style="text-align: right">
<a href="/tweet/{{ tw.id }}">
<span class="badge rounded-pill bg-success">보기</span>
</a>
</div>
<div class="media">
<div class="media-body">
<h5 class="mt-0">{{ tw.content }}</h5>
</div>
<div style="text-align: right">
<span style="font-size: small">{{ tw.author.username }}-{{ tw.created_at|timesince }} 전</span>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
화면이 잘 출력되는 것을 볼 수 있다.
tweet/delete/<int:id> 페이지로 삭제 url을 만들어준 뒤 urls.py를 통해 연결해준다.
urlpatterns = [
path('', views.home, name='home'), # 127.0.0.1:8000 과 views.py 폴더의 home 함수 연결
path('tweet/', views.tweet, name='tweet'), # 127.0.0.1:8000/tweet 과 views.py 폴더의 tweet 함수 연결
path('tweet/<int:id>',views.detail_tweet, name='detail-tweet'),
path('tweet/delete/<int:id>', views.delete_tweet, name='delete-tweet'),
]
이때 로그인된 사용자만 트윗 삭제를 할 수 있게 만들어야 하므로 데코레이터 login_required 로 def delete_tweet() 을 감싸준다.
from django.contrib.auth.decorators import login_required
@login_required
def delete_tweet(request, id):
my_tweet = TweetModel.objects.get(id=id)
my_tweet.delete()
return redirect('/tweet')
def delete_tweet 에서는 tweet 의 id를 받아서 해당 id 를 갖고 있는 트윗을 데이터베이스에서 찾은 뒤, 그 트윗을 삭제(delete()) 해준다.
제대로 삭제된 것을 볼 수 있다.
트윗의 보기 버튼을 누르면 트윗 상세 페이지에 들어가 댓글을 쓰고 삭제할 수 있게 만들 것이다.
우선 트윗 상세 페이지와 댓글을 삭제, 등록할 수 있는 url 을 만들고 연결해준다.
urls.py
urlpatterns = [
path('', views.home, name='home'), # 127.0.0.1:8000 과 views.py 폴더의 home 함수 연결
path('tweet/', views.tweet, name='tweet'), # 127.0.0.1:8000/tweet 과 views.py 폴더의 tweet 함수 연결
path('tweet/<int:id>',views.detail_tweet, name='detail-tweet'),
path('tweet/comment/<int:id>',views.write_comment, name='write-comment'),
path('tweet/comment/delete/<int:id>', views.delete_comment, name='delete-comment'),
path('tweet/delete/<int:id>', views.delete_tweet, name='delete-tweet'),
]
이후 view.py 에 write_comment 함수와 delete_commet 함수를 추가해준 뒤 id 를 통해 해당 트윗을 받아 화면에 출력해준다. 화면을 출력해주는 것이므로 request method 는 get 이고, get 방식으로 요청이 들어온다면 tweet_detail.html 을 렌더링해줄 것이다.
내 트윗과 코멘트를 출력해줘야 하므로 데이터에는 my_tweet, all_comment 를 담아 보낸다.
@login_required
def detail_tweet(request, id):
my_tweet = TweetModel.objects.get(id=id)
all_comment = TweetComment.objects.all().filter(tweet_id=id) # 해당 트윗의 id 를 갖고 있는 댓글만 출력
if request.method == 'GET':
return render(request,'tweet/tweet_detail.html',{'tweet':my_tweet, 'comment' : all_comment})
그러면 tweet_detail.html 에서는 tweet 을 받아 content 와 author 을 출력해줄 것이고, all_comment 를 받아 차례대로 트윗의 댓글을 모두 출력해줄 것이다.
각 트윗마다 다른 댓글이 잘 출력되는 것을 볼 수 있다.
트윗 아래의 댓글에 의견을 작성하고 작성 버튼을 누르면 데이터베이스에 저장됨과 동시에 페이지가 reload 되게 만들 것이다.
우선 댓글의 author 는 접속해있는 user 가 될 것이므로 user 객체가 필요하고, 댓글 모델 객체도 하나 필요하다.
user = request.user
my_comment = TweetComment()
이후 html의 텍스트박스에서 데이터를 받아 TweetComment 인스턴스인 my_comment 에 차례로 정보를 넣어준다.
my_comment.comment = request.POST.get('comment',' ')
my_comment.author = user
my_comment.tweet_id = id
my_comment.save()
이 다음 redirect 될 주소를 넣어주면
re_add = reverse('detail-tweet', args=(id,))
return redirect(re_add)
이번에는 댓글의 id를 받아서 삭제하는 delete_comment 함수를 구현해줄 것이다. 트윗 삭제 함수와 별반 다르지 않지만, 이번에는 댓글의 id 를 받았기 때문에 args=(id,) 가 들어가는 것이 아니라 댓글의 속성 중 하나인 tweet_id 를 args 에 넣어 redirect 해줘야 한다.
@login_required
def delete_comment(request, id):
my_comment = TweetComment.objects.get(id=id)
my_comment.delete()
re_add = reverse('detail-tweet', args=(my_comment.tweet_id,)) # 이 부분!
return redirect(re_add)
끝!