Django 03

·2023년 9월 1일
0

파이썬

목록 보기
8/18

로그인 후 tweet 페이지 만들기

이번에는 로그인 후 트윗을 올리고 그 트윗을 선택하면 댓글을 달 수 있는 상세 페이지가 보이게 만드려고 한다.

우선 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() 을 감싸준다.

  • is_authenticated 는 데이터베이스에 있는 인증된 사용자인지 검사하는 것이고, login_required 는 로그인이 되어있는지 검사하는 것이다.
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()) 해준다.

제대로 삭제된 것을 볼 수 있다.

tweet 상세 페이지 / 댓글

상세 페이지

트윗의 보기 버튼을 누르면 트윗 상세 페이지에 들어가 댓글을 쓰고 삭제할 수 있게 만들 것이다.
우선 트윗 상세 페이지와 댓글을 삭제, 등록할 수 있는 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)
  • detail-tweet url 의 <int:id> 변수로 id 를 넣어줘야 했는데, 그냥 id 를 넣으니 iterater 가 들어와야 하는 자리라 int 는 넣을 수 없다는 타입에러가 뜨길래 쉼표(,) 를 넣어 리스트로 바꿔주었다.

    댓글이 잘 저장되어 출력되는 것을 볼 수 있다.

삭제

이번에는 댓글의 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)

끝!

profile
공부 중

0개의 댓글