[0529] TIL 33일차

nikevapormax·2022년 5월 27일
0

TIL

목록 보기
30/116

😂 Django 3주차

😭 사용자 모델

- django와 나의 사용자 모델 비교

  • django에서 기본적으로 제공하는 사용자 모델은 auth_user이고, 내가 만든 사용자 모델은 my_user이다.

  • auth_user의 경우, 내가 직접 만들었던 user model보다 더 많은 속성을 가지고 있다.
    • 해당 모델을 사용하게 되면, django에서 제공하는 기능들을 사용해 과정이 훨씬 간결해진다.
    • 우리가 my_user model을 만들어 사용자 관리에 들어가게 되면 session을 사용하는 등의 과정을 거쳐 보안을 적용해야 하지만, auth_user model을 사용하게 되면 그런 과정을 거치지 않아도 된다.

- 우리의 user model 업그레이드하기

  • class의 상속
    • 만약 class B에서 class C의 기능을 사용하고 싶다면, 추가적인 코드를 작성하지 않고 class B(C)라고 작성하여 class C의 기능을 상속받아 사용할 수 있다.

    • 이미 이전 주차에서 작성했었던 user/models.py에서 class의 상속이 있었다.

    • class UserModel(models.Model)를 보면 UserModel에서 models.Model의 기능을 상속받아 사용하겠다는 뜻이다.

      #user/models.py
      from django.db import models
      
      class UserModel(models.Model):
         # DB 테이블의 이름을 지정하는 등 데이터베이스의 정보를 넣어주는 역할
         class Meta:
            db_table = "my_user"
  • user model 수정
    • 현재 auth_user와 연동되는 AbstractUser를 상속받아 사용하기 때문에 이전에 직접 작성하였던 것중 auth_user의 내용과 중복되는 것들을 삭제해 주었다.
    • 그리고 추가하고 싶은 것은 그대로 놔뒀다.
##### user/models.py #####

from django.db import models
# 우리는 django에서 기본적으로 제공하는 user 모델을 사용하겠다.
# AbstractUser는 django에서 기본적으로 제공하는 user model
from django.contrib.auth.models import AbstractUser


class UserModel(AbstractUser):
    # DB 테이블의 이름을 지정하는 등 데이터베이스의 정보를 넣어주는 역할
    class Meta:
        db_table = "my_user"

    # 원래 이전에 작성했던 usename, password, created_at, updated_at은 이미 auth_user에 존재
    # 그러므로 그것들은 다 지우고, 우리가 추가하고 싶은 bio만 작성해주면 됨!
    # 상세 정보
    bio = models.CharField(max_length=256, default='')
  • 변경된 user model 적용하기
    • mySpartaSns/settings.py
      • 맨 아래에 해당 코드를 넣어주면 된다.
      • django의 기본 모델을 우리가 우리 입맛대로 튜닝한 것이기 때문에 django에게 해당 사실을 알려주어 django가 추후 우리가 바꾼 모델을 기본 모델로써 잘 쓸 수 있도록 조치하는 것이다.
# mySpartaSns/settings.py
# django의 기본 모델에 다른 정보를 끼워넣어 그것을 우리의 User model로 사용하기로 했기 때문에
# 그것을 django에게 알려주어야 한다. 
AUTH_USER_MODEL = 'user.UserModel'

- user model을 데이터베이스에 적용

  • 2주차에서 새로운 model들을 만들고 데이터베이스에 적용했던 것과 똑같이 진행하면 된다.
  • 아래의 코드를 terminal에 입력해주면 된다.
$ python manage.py makemigrations 
$ python manage.py migrate
  • my_user에서 auth_user의 내용을 상속받아 사용하면서 기존 내용을 삭제하는 변화가 일어났기 때문에 아래의 메세지들에서 알 수 있듯이 변화가 일어나고 그 변화를 적용해준 것을 볼 수 있다.
  • 데이터베이스 창에서 확인해 보면 아래와 같이 잘 적용된 것을 알 수 있다.

😭 회원가입 수정

- user/views.py

  • 우리는 이제 django에서 기본적으로 제공하는 기능을 사용해 user model을 만질 수 있게 되었다. 그러므로 django에서 제공하는 함수를 가져다가 회원가입 기능을 좀 수정하도록 하겠다.
  • 먼저, 모듈을 import 해준다.
# 사용자가 데이터베이스 안에 있는지 검사하는 함수
from django.contrib.auth import get_user_model
  • 그리고 앞에 있는 회원의 정보를 프론트에서 받아오는 기능과 비밀번호를 더블체킹하는 부분은 필요하다고 생각이 되니 살려주고, 그 아래에 있는 이미 데이터베이스에 있는 user인지 판별하는 부분을 수정하도록 하겠다.
    • 위에서 import한 기능을 사용하도록 수정하였다.
 # 위에서 import한 get_user_model을 사용해 이미 있는 user인지 판별해줌
 not_new_user = get_user_model().objects.filter(username=username)

 # 이미 정보를 입력한 user가 존재한다면?
 # filter 기능을 통해서 같은 이름이 있는지 걸러준다.
 # not_new_user = UserModel.objects.filter(username=username)
  • 앞의 검증을 통과하게 된다면 우리는 사용자가 입력한 정보를 데이터베이스에 넣어주는 과정을 거쳐야 한다. 해당 코드를 줄여보도록 하겠다.
 if not_new_user:
    return render(request, 'user/signup.html')
 else:
    UserModel.objects.create_user(username=username, password=password, bio=bio)
    # new_user = UserModel()
    # new_user.username = username
    # new_user.password = password
    # new_user.password2 = password2
    # new_user.bio = bio
    # 위에서 받아온 정보들을 저장하는 과정을 거처야 함 꼭!
    # new_user.save()

    # 위와 같이 회원정보를 성공적으로 저장하게 되면 로그인 페이지로 리다이렉트해준다.
    return redirect('/sign-in')
  • 회원 정보가 저장된 것을 확인할 수 있으며, 이전 코드의 결과와 달리 password에도 암호화가 되어 있는 것을 확인할 수 있다.

😭 로그인 수정

  • 이전의 코드를 보게 되면 django의 기본 모델을 가져다 쓰기 전의 비밀번호는 해싱이 되어 있지 않다. 그러므로 현재 코드를 그대로 사용하게 된다면 해싱된 비밀번호와 해싱되지 않은 비밀번호를 계속 대조하는 것이므로 절대로 로그인에 성공할 수 없을 것이다.
  • 따라서 아래와 같이 코드를 변경해주도록 하겠다.
    • authenticate 모듈을 활용해 사용자 인증을 해준다.
# authenticate : 입력한 비밀번호와 해싱된 비밀번호가 일치하는지, 그것과 사용자가 일치하는지 한 번에 확인해줌
me= auth.authenticate(request, username=username, password=password)
# 앞에 있는 username은 UserModel 안에 있는 username이다. 뒤에 있는 것은 우리가 입력한 username이다.
# me = UserModel.objects.get(username=username)
  • 아래의 비밀번호 일치를 확인하는 코드도 변경이 되어야 한다. 비밀번호를 굳이 확인할 필요가 없이, 바로 위에서 사용자 인증을 한 내용이 있는지 없는지만 판단하면 된다.
if me.password == password:
   request.session['user'] = me.username
           ⬇️
if me is not None:
   auth.login(request, me)

😭 tweet

- tweet/views.py

  • 사용자가 로그인을 하게되면 보여질 페이지에 대해 설정하고, 만약 로그인에 실패하게 된다면 보여질 페이지에 대해서도 설정하였다.
from django.shortcuts import render, redirect


def home(request):
    # user가 로그인되어 있는지 확인할 수 있음
    user = request.user.is_authenticated
    if user: # user가 로그인되어 있으면
        return redirect('/tweet') # /tweet 으로 리다이렉트 해주고
    else: # 로그인되어 있지 않다면
        return redirect('/sign-in') # 로그인 페이지로 리다이렉트 해준다.

def tweet(request):
    if request.method == 'GET':
        return render(request, 'tweet/home.html')

- tweet/urls.py

  • views.py에서 작성한 함수들을 url과 묶어주었다.
# tweet/urls.py
from django.urls import path
from . import views

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 함수 연결
]
  • 위와 같이 세팅을 하고 나서 http://127.0.0.1:8000/로 들어가게 되면 다음과 같은 이쁜 화면이 나오게 된다.
  • 나는 세팅을 다 했는데 왜 이런 개같은 화면이 나오지? 라고 생각하기 전에, 내가 뭘 안했나 생각을 해보았더니 mySpartaSns에 포함되어 있는 내 django 프로젝트의 모든 세팅과 url의 정보가 담겨 있는 파일들을 수정하지 않음을 알게 되었다. 그러므로 수정을 시작해보겠다.
  • mySpartaSns/urls.py
    • client의 요청이 들어오면 가장 먼저 해당 파일로 와서 내가 가진 url이 여기 없나하고 확인을 하게 된다.
    • 만약 내가 가진 url값이 있다면 거기로 잘 넘어가지만, url이 설정되어 있지 않다면 아까와 같은 page not found가 되버린다.
    • 우리는 url을 설정해주었고, 아래와 같이 페이지가 잘 나오게 된다.
from django.contrib import admin
from django.urls import path, include

# 현재 내가 있는 파일에서 views.py를 불러옴
from . import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('test/', views.base_response, name='first_test'),
    path('first/', views.first_view, name='first_view'),
    # spartaSns와 user의 url이 연결되었다!!
    path('', include('user.urls')),
    path('', include('tweet.urls')),
]

  • 이렇게 설정을 하고 다시 로그인을 해보면 다음과 같은 화면이 나오게 된다. 이는 우리가 맨 처음 로그인을 설정할 때 작성했던 것인데, 로그인에 성공하면 다른 페이지로 넘어가는 트리거가 없기 때문에 그냥 이전처럼 이름만 띡 나오고 끝인 것이다. 따라서 이를 바꿔주도록 하겠다.
 if me is not None:
    auth.login(request, me)
    return redirect('/')

😭 로그인 시 home 화면 변경

- 기존 화면

  • 로그인이 완료된 상태임에도 user의 정보가 하나도 보이지 않는다.
  • 로그인을 완료하였는데 Sign inSign Up 버튼이 계속 보여지고 있다.

- 화면 수정

  • 먼저, 로그인한 사용자의 개인 정보를 화면에 표시해주도록 하겠다.
  • 우리가 이전에 사용했던 template 문법을 통해 개인 정보를 표시할 것이며, 해당 수정은 templates/tweet/home.html에서 이루어졌다.
  • 현재 상태는 왼쪽 컬럼에 사용자의 정보를 나타낸 것이고, 다른 부분은 아직 수정하지 않았다.
    • 우리가 django의 기본 auth_model과 우리가 만든 user_model을 합친 모델에서 우리에게 필요한 정보인 usernamebio를 가져와 반영시켜주었다.
<!-- base.html을 기본으로 가져가고, 남는 공간에 content를 붙여 넣겠다. -->
{% extends 'base.html' %}

{% block content %}
    <div class="container timeline-container">
        <div class="row">
            <!-- 왼쪽 컬럼 -->
            <div class="col-md-3">
                <div class="card">
                    <div class="card-body">
                        <h5 class="card-title">{{ user.username }}</h5>
                        <p class="card-text">{{ user.bio }}</p>

                    </div>
                </div>
            </div>
  • 그 다음 Sign inSign Up 버튼 부분을 수정해주도록 하겠다.
  • 똑같이 template 문법을 사용하며, 이번에는 조건문을 사용하기 위해
    {% .... %}를 사용하도록 하겠다.
<form class="form-inline my-2 my-lg-0">
    <!-- 유저가 인증이 되었니?(로그인이 완료된 사용자니?)에 대해 묻는 조건문 -->
    <!-- sign in과 sign up 버튼이 보이려면 로그인이 되어 있지 않아야 한다. -->
    <!-- 만약 사용자 인증이 되어 있지 않다면 -->
    {% if not user.is_authenticated %}
    <ul class="navbar-nav mr-auto">
        <li class="nav-item active">
           <a class="nav-link" href="/sign-in"> Sign In <span class="sr-only"></span></a>
        </li>
        <li class="nav-item active">
            <a class="nav-link" href="/sign-up"> Sign Up <span class="sr-only"></span></a>
         </li>
    </ul>
    <!-- 사용자 인증이 완료된 사용자라면 이름을 보여줘 -->
    {% else  %}
       {{ user.username }}님 반갑습니다~!
    <!-- if문 종료 -->
    {%  endif %}
</form>

- 새로운 문제점

  • 브라우저의 시크릿 모드를 통해 우리의 http://127.0.0.1:8000/tweet으로 들어가게 되면 아래의 화면이 나오게 된다.
  • 여기서 이게 왜 문제야? 라는 생각이 들면 안된다. 왜냐하면 아래 페이지는 우리가 로그인을 해야만 볼 수 있는 페이지이고, 우리가 위에서 로그인한 사람의 정보가 나오도록 조치했는데 그런 내용이 하나도 없는 것을 보면 로그인을 하지 않은 상태에서도 해당 페이지에 갈 수 있도록 길이 나있는 것 같다.
  • 이 문제점을 해결하기 위해 해당 url을 가지고 있는 tweet/urls.py로 먼저 들어가 보았다.
    • 찾아보니 /tweet 이라는 url이 존재하고, 해당 url에 접속하게 되면 tweet/views.py에 있는 tweet 함수가 실행된다는 것을 알 수 있었다.
      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 함수 연결
      ]
  • 그래서 나는 tweet/views.py로 들어가 tweet 함수를 찾았고, 해당 내용을 수정하기로 하였다.
def tweet(request):
    if request.method == 'GET':
        # 사용자 인증에 대한 정보를 user 변수에 대입
        user = request.user.is_authenticated
        # 만약 사용자 인증이 되어 있다면
        if user:
            # tweet/home.html 로 사용자가 갈 수 있도록 함
            return render(request, 'tweet/home.html')
        else:
            # 사용자 인증이 되지 않았으므로 로그인 화면으로 보내줌
            return redirect('/sign-in')
  • 사용자 인증 기능을 추가했고, 아래의 사진처럼 로그인이 되지 않은 사람을 걸러내 로그인 시도를 먼저 할 수 있도록 해줄 수 있었다.
  • 사용자가 로그인에 성공하게 되면, 이전과 같이 로그인한 사용자의 정보가 제공되는 화면으로 들어올 수 있었다.

- 새로운 문제점2

  • 이미 로그인한 사용자는 굳이 회원가입로그인 페이지에 접속할 필요가 없다. 현재의 상태로는 url을 만지지 않고 흘러가는데로 html 안에서만 과정을 진행한다면 문제될 것이 없었다. 그런데 url을 만지는 순간 로그인을 했는데도 페이지가 이동되는 것을 알 수 있었다.

  • 해당 문제를 해결하기 위해 회원가입로그인이 이루어지는 user/views.py를 수정해보도록 하겠다.

    • 앞에서 수정했던 부분은 그대로 가져가면서, method == 'GET'인 부분의 코드를 수정해 보았다.

    • redirect('/')를 한 이유는 /를 담당하는 함수는 tweet/views.pyhome 함수이고, 해당 함수에서 사용자 인증에 성공하면 /tweet으로 redirect를 해주기 때문에 그냥 /를 사용했다.

    • 아래의 tweet/urls.py를 확인해 보면, url이 없는 경우에 즉 http://127.0.0.1:8000/인 경우에 home 함수가 실행이 되는 것을 알 수 있다.

    • 그 다음 사진을 확인해 보면, home 함수에서 사용자 인증이 되어 있다면 /tweet으로 url을 설정해주는 것을 알 수 있다.

# 뒷부분 생략

def sign_up_view(request):
    if request.method == 'GET':
        # user 변수에 사용자 인증 정보를 담는다. 
        user = request.user.is_authenticated
        # 만약 사용자 인증이 되어 있다면
        if user:
            # home으로 바로 이동시켜주고
            return redirect('/')
        # 만약 사용자 인증이 되어 있지 않다면
        else:
            # 회원가입 페이지로 보내준다.
            return render(request, 'user/signup.html')
# 앞부분 생략

def sign_in_view(request):
       elif request.method == 'GET':
        user = request.user.is_authenticated
        if user:
            return redirect('/')
        else:
            return render(request, 'user/signin.html')

- 로그아웃 기능

  • 위의 로그인 및 회원가입과 마찬가지로 로그아웃 기능도 user와 관련된 기능이기 때문에 user/views.py를 수정해주도록 하겠다.
  • 먼저 로그아웃 기능을 수행하는 함수를 그냥 작성하였다.
def logout(request):
    auth.logout(request)
    return redirect('/')
  • '이렇게 간단할리가 없지'라는 생각은 항상 옳다. 우리는 윗 코드를 작성할 때 사용자가 로그인한 사용자인지 아닌지 판단을 해주지 않았다. 그래서 다시 작성하도록 하겠다.
# 다른 부분 생략

from django.contrib.auth.decorators import login_required

# 사용자가 로그인이 되어있어야만 접근 가능하다고 알려주는 함수
@login_required
def logout(request):
    auth.logout(request)
    return redirect('/')
  • 함수를 작성해주었으니 user/urls.py에서 url을 설정하도록 하겠다.
from django.urls import path
from . import views

urlpatterns = [
    # sign-up/ 으로 들어가면 views.py에 있는 sign_up_view 함수가 실행된다. (해당 함수는 signup.html로 render 해준다.)
    path('sign-up/', views.sign_up_view, name='sign-up'),
    # sign-in/ 으로 들어가면 views.py에 있는 sign_in_view 함수가 실행된다. (해당 함수는 signin.html로 render 해준다.)
    path('sign-in/', views.sign_in_view, name='sign-in'),
    path('logout/', views.logout, name='logout'),
]
  • 이제 화면에 로그아웃 버튼을 만들어주도록 하겠다. 가장 기본 화면인 base.html에 작업을 해주었다.
<!-- 윗부분 및 아랫부분 생략 -->

<form>
   <!-- 사용자 인증이 완료된 사용자라면 이름을 보여줘 -->
            {% else %}
                <ul class="navbar-nav mr-auto">
                    # 해당 부분이 선택되지 않도록 disabled 작성
                    <li class="nav-item disabled">
                        <span class="nav-link">
                            {{ user.username }} 님, 반갑습니다~!
                        </span>
                    </li>
                    <li class="nav-item active">
                        <a class="nav-link" href="/logout">logout</a>
                    </li>
                </ul>
            <!-- if문 종료 -->
            {% endif %}
</form>
  • 아래 사진과 같이 로그아웃 버튼이 생긴 것을 볼 수 있다.
  • 로그아웃 버튼을 눌러 작동이 잘 되나 확인을 해보았다. 완벽하다.

😭 게시글 쓰기

- 게시글 저장

  • 메인 페이지를 보면 게시글을 입력할 수 있는 textarea가 존재한다. 해당 부분에 글을 입력하고 버튼을 누르게 되면 게시글이 POST 요청이 되어 db에 저장되는 부분까지 진행해 보겠다.
  • 우선 해당 부분이 존재하는 html 파일인 home.html을 열어 구조를 확인하고 수정을 하도록 하겠다.
    • 아무나 게시글을 볼 수 없도록 암호화를 진행하였다.
    • <form>태그 안의 내용이 버튼을 누르면 전송될 수 있도록 method와 action을 설정해 주었다.
<!-- 글을 작성 하는 곳 -->
<div class="row mb-2">
    <div class="col-md-12">
        <div class="card">
            <div class="card-body">
                <div class="media">
                    <div class="media-body">
                        <h5 class="mt-0">나의 이야기를 적어주세요</h5>
                        <p>
                        <form action="/tweet/" method="post">
                            <!-- 암호화 진행 -->
                            {% csrf_token %}
                             <div class="form-group mb-2">
                                 <textarea class="form-control" style="resize: none" name='my-content' id="my-content"></textarea>
                             </div>
                             <button type="submit" class="btn btn-primary" style="float:right;">작성하기</button>
                        </form>
                        </p>
                     </div>
                  </div>
              </div>
          </div>
     </div>
</div>
  • 게시글이 db에 잘 저장된 것을 확인할 수 있다.

- 게시글 보여주기

  • 방금 전 나는 db에 내가 작성한 게시글을 저장하였다. 하지만 이것이 화면에는 보이지 않았다. 따라서 화면에 게시글이 보여지도록 조치를 취하도록 하겠다.
  • tweet/views.py
    • all_tweet이라는 변수를 만들어, 해당 변수 안에 사용자가 입력한 TweetModel 안에 있는 모든 정보를 저장하게 된다.
    • 그리고 flask 때와 같이, return 값으로 프론트에게 돌려준다.
# 뒷 부분 생략

def tweet(request):
    if request.method == 'GET':
        # 사용자 인증에 대한 정보를 user 변수에 대입
        user = request.user.is_authenticated
        # 만약 사용자 인증이 되어 있다면
        if user:
            # tweet 모델에 저장한 모든 데이터를 불러올 거야. 그런데 순서는 시간 순서가 아닌 최신순으로 불러와줘.
            all_tweet = TweetModel.objects.all().order_by('-created_at')
            
            # tweet/home.html 로 사용자가 갈 수 있도록 함
            return render(request, 'tweet/home.html', {'tweet': all_tweet})
        else:
            # 사용자 인증이 되지 않았으므로 로그인 화면으로 보내줌
            return redirect('/sign-in')
  • template/tweet/home.html
    • tw.author.username는 tweet의 models.py에서 볼 수 있듯이 author는 외래키로 UserModel의 값을 받아와 쓰고 있다. 그러므로 username을 명시하지 않으면 UserModel의 모든 값이 나오게 되므로 명시를 해줘야 한다.
<!-- 작성 된 글이 나오는 곳 -->
<div class="row">
    <!-- views.py에서 게시글의 모든 정보를 tweet으로 넘겨줬음 -->
    {% for tw in tweet %}
    <div class="col-md-12">
         <div class="card">
              <div class="card-body">
                   <div class="media">
                       <div class="media-body">
                           <h5 class="mt-0">{{ tw.content }}</h5>
                       </div>
                       <div style="text-align: right;">
                            <!-- tw.author.username인 이유는 tweet의 models.py에서 볼 수 있듯이 author는 외래키로 UserModel
                            의 값을 받아와 쓰고 있다. 그러므로 username을 명시하지 않으면 UserModel의 모든 값이 나오게 되므로 명시를 해줘야 한다. -->
                            <!-- tw.created_at은 그냥 가져오게 되면 몇월 몇일 몇시 몇분까지 다 들고오게 되므로, timesince(django 기본제공 함수)를 적용해준다.-->
                            <span style="font-size: small">{{ tw.author.username }} - {{ tw.created_at|timesince }} 전</span>
                       </div>
                   </div>
               </div>
          </div>
     </div>
     {% endfor %}
</div>

- 게시글 삭제하기

  • 게시글을 삭제할 때는 특정 게시글을 삭제하는 것이기 때문에, 어떤 게시글인지 지정해주는 작업이 필요하다.
    http://127.0.0.1:8000/tweet/delete/게시글의id
  • tweet/views.py
    • 인자로 받아온 id값을 가지고 TweetModel에서 같은 id인 게시글을 my_tweet 변수에 저장하고, 이것을 삭제한 후 /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')
  • 함수를 생성했으니, tweet/urls.py로 가서 url을 생성해주도록 하겠다.
# tweet/urls.py
from django.urls import path
from . import views

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/delete/<int:id>', views.delete_tweet, name='delete-tweet'),
]
  • home.html에서 삭제 버튼을 만들도록 하겠다.
    • 사용자의 로그인 정보를 활용하여 로그인한 사람이면 삭제를 할 수 있도록 조치해주고, 아닌 사람들은 하지 못하게 하였다.
<!-- 작성 된 글이 나오는 곳 -->
<div class="row">
    <!-- views.py에서 게시글의 모든 정보를 tweet으로 넘겨줬음 -->
    {% for tw in tweet %}
    <div class="col-md-12">
         <div class="card">
              <div class="card-body">
                   <!-- 만약 이 글을 쓴 작성자가 현재 로그인한 사용자라면-->
                   {% if tw.author == user %}
                       <div style="text-align: right">
                           <!-- a 태그를 사용해 url로 이동할 수 있게 해줌 -->
                           <a href="/tweet/delete/{{ tw.id }}">
                               <span class="badge rounded-pill bg-danger">삭제</span>
                           </a>
                        </div>
                    {% endif %}
                    <!-- 만약 현재 글을 보고 있는 사람이 로그인한 사용자가 아니라면 -->
                    <div style="text-align: right">
                         <a href="#">
                             <span class="badge rounded-pill bg-success">보기</span>
                         </a>
                    </div>
   <!-- 아래 부분 생략-->                              
profile
https://github.com/nikevapormax

0개의 댓글