본문 바로가기
Django(웹서비스 만들기)

[4주차] 사용자별 정보 다르게 출력하기

by SOHEE- 2021. 12. 16.

로그인 사용자의 프로필 이미지 출력하기

로그인 사용자를 식별할 수 있도록 클라이언트에서 올라오는 정보(request)의 세션 필드를 활용하여 네비게이션 바에 각 사용자별 프로필 이미지를 출력하도록 설정합니다. 

 

세션 필드에 email, 로그인 정보 넣기

로그인 로직(class Login)에서 로그인이 성공하는 부분에 아래와 같이 email과 로그인이 성공했음을 체크할 값을 넣어주는 코드를 입력합니다.

user/views.py

 

프로필 이미지 출력 코드 수정

메인 웹 페이지에 사용자별 프로필 이미지를 출력하려면 사용자를 식별할 수 있는 데이터를 main.html에 보내줘야 하기 때문에 메인 views.py의 Main 클래스의 코드를 수정합니다. 

if문을 사용해 로그인이 성공했는지 확인하고 세션에서 가져온 email과 user DB에 저장된 email이 같은 정보를 find_user에 넣어서 user_info 라는 이름으로 context에 저장하여 main.html에 넘겨줍니다. 

views.py

user_info는 로그인한 사용자의 모든 열의 정보를 리스트 형태로 담고 있기 때문에 user_info.{열이름} 형태로 불러와 사용할 수 있습니다.

main.html의 네비게이션바 아이콘 코드 부분

 

댓글 입력받아 출력하기

댓글 입력 받기

1. 댓글 저장을 위한 DB table 만들기

models.py에서 Reply라는 모델을 생성하고, 그 아래 파이썬 명령어를 터미널에서 입력하여 실행합니다. 

class Reply(models.Model):
    feed_id = models.IntegerField()
    nickname = models.TextField()
    content = models.TextField()
python manage.py makemigrations
python manage.py migrate

 

2. 게시 버튼 동작을 위한 코드 작성하기

'게시' 버튼이 있는 위치에 'write_reply'라는 이름의 클래스를 추가하고, 추후 jquery 작성 시 $(this)prev()를 사용하기 위해 <div>로 나눠져있던 게시 부분을 댓글 입력을 받는 폼컨트롤 공간에 <span>으로 변경해 넣어줍니다.

$(this)는 현재 실행중인 코드 위치를 나타내며 prev()는 바로 그 전 단계의 코드를, next()는 바로 그 다음 단계의 코드를 나타냅니다.

<div style="display: flex; flex-direction: row; width: 100%">
    <input class="form-control" type="text" placeholder="댓글입력">
    <span class="write_reply" style="width: 50px"> 게시 </span>
</div>

 

3. jquery로 입력받은 데이터 백엔드로 넘기기 

$('.write_reply').click(function(){
    const content = $(this).prev().val();
    const nickname = "{{ user_info.nickname }}";
    const feed_id = $(this).attr('feed_id'); 
	//span 위치에 feed_id="{{i.id}}" 추가하여 Feed ID를 가져옵니다.

        $.ajax({  //login에서 작성한 ajax를 복사하여 수정하면 편합니다.
            url: "http://127.0.0.1:8000/reply/",
            method: "POST",
            data: {
                content: content,
                nickname: nickname,
                feed_id: feed_id
                },
                success: function (data) {
                    console.log("성공");
                    alert("댓글쓰기 성공");
                },
                error: function (request, status, error) {
                    console.log("에러");
                    alert("댓글쓰기 실패");
                },
                complete: function () {
                    console.log("무조건실행");
                }
            });
}

 

4. views.py에서 table에 데이터 생성하는 코드 작성하기

class CreateReply(APIView):
    def post(self, request):
        feed_id = request.data.get('feed_id')
        content = request.data.get('content')
        nickname = request.data.get('nickname')

        Reply.objects.create(content=content,feed_id=feed_id,nickname=nickname)
        return Response(status=200, data=dict(message="댓글 쓰기 성공"))

 

5. urls.py에서 경로 지정하기

urls.py 파일에 가서 path('reply/', CreateReply.as_view()) 를 입력합니다.

 

댓글 테이블 정보로 화면에 댓글 표시하기

1. views.py의 Main 클래스 수정하기

메인의 views.py에서 피드정보를 data_list로 전달하는 과정에서 댓글정보도 포함하여 전달할 수 있도록 수정합니다. 이때 댓글정보(table:content_reply)는 피드정보(table:content_feed)와 다른 테이블에 존재하기 때문에 아래와 같이 리스트를 재구성 해야 합니다.

data_list = []
for feed in Feed.objects.all().order_by('-id'):
#Feed.objects.all() ⇒ [피드1, 피드2, 피드3, ...]
    data_list.append(
		    dict(id=feed.id,
             image=feed.image,
             profile_image=feed.profile_image,
             nickname=feed.nickname,
             content=feed.content,
             reply_list=Reply.objects.filter(feed_id=feed.id) #[댓글1,댓글2,..]
             )
         )

 

2. 댓글 출력 코드 수정하기

하드코딩으로 넣었던 댓글 입력 부분을 아래와 같은 코드로 수정합니다.

<div>
{% for j in i.reply_list %}
	<div style="font-size: 13px">
		<b>{{ j.nickname }}</b> {{ j.content }}
	</div>
{% endfor %}
</div>

 

3. Front에서 별도로 댓글 적용 처리하기

웹 상에서 입력한 값이 DB에 저장되고 이 정보를 웹으로 다시 불러와 표시하려면 화면의 새로고침이 되어야 합니다. 하지만 새로고침 없이 프론트에서 별도로 입력된 값을 처리하여 화면에 출력하도록 구성할 수 있습니다. 
front 설정이므로, main.html의 write_reply ajax 부분에 아래와 같이 코드를 추가해줍니다.

//입력한 댓글을 화면에 출력
$(this).parent().parent().prev().append(
    '<div style="font-size: 13px"><b>'+ nickname +'</b> '+ content +' </div>'
);
//댓글 입력후에 입력창의 글자를 지우기
$(this).prev().val('');

 

좋아요 설정하기

1. models.py에서 좋아요(Like) 적용 여부를 확인할 DB table 생성

class Like(models.Model):
	feed_id = models.IntegerField()
	email = models.TextField()

	class Meta:  # 한 피드에 여러번 좋아요를 할 수 없게 메타데이터를 구성합니다.
		unique_together = ('feed_id', 'email')


2. main.html에서 하트 아이콘을 눌렀을 때 색 변환 코드 작성

부트스트랩에서 받아온 하트아이콘은 테두리만 있는 favorite_border와 색이 채워지는 favorite 두 가지 타입이 있는데, 이 명칭을 사용하여 좋아요 누름과 취소를 구현하려고 합니다. 
우선 하트 아이콘이 있는 위치에 favorite 이름으로 class를 추가하고 jquery 부분에 아래와 같이 입력합니다. 

$('.favorite').click(function () {
    if ($.trim($(this).html()) == 'favorite_border') {
        // '좋아요' 누름
        $(this).html('favorite')

    } else {
        // '좋아요' 취소
        $(this).html('favorite_border')
    }
});

`$(this).html()`은 현재 실행 위치의 html 값을 가져올 수 있는 코드이며 괄호 안을 비워두면 값을 가져오고, 안에 내용을 넣으면 replace 시킵니다.

 

3. main.html에서 하트 아이콘을 눌렀을 때의 정보를 DB table에 전달하는 ajax 코드 작성

email은 로그인 사용자 정보를 받은 것에서 가져오고, feed id는 favorite html 코드 위치에 속성으로 feed_id="{{ i.id }}"를 넣어주고 가져옵니다.

const email = "{{ user_info.email }}";
const feed_id = $(this).attr('feed_id');

$.ajax({
    url: "http://127.0.0.1:8000/like/",
    method: "POST",
    data: {
        email: email,
        feed_id: feed_id
    },
    success: function (data) {
        console.log("성공");
    },
    error: function (request, status, error) {
        console.log("에러");
    },
    complete: function () {
        console.log("무조건실행");
    }
});

 

4. content/views.py에 Like 동작 로직 작성

class CreateLike(APIView):
    def post(self, request):
        feed_id = request.data.get('feed_id')
        email = request.data.get('email')
				
	# feed id와 email 받아서 테이블 생성
        Like.objects.create(feed_id=feed_id, email=email)

        return Response(status=200, data=dict(message="좋아요 성공"))

class CancelLike(APIView):
    def post(self, request):
        feed_id = request.data.get('feed_id')
        email = request.data.get('email')

	# feed id와 email이 매칭되는 행을 찾아서 삭제
        find_like = Like.objects.filter(feed_id=feed_id, email=email).first()
        find_like.delete()

        return Response(status=200, data=dict(message="취소 성공"))

 

5. urls.py에서 Like 실행 관련 경로 작성

다음 두 경로를 urls.py에 추가해줍니다. 

path('like/', CreateLike.as_view()),
path('cancellike/', CancelLike.as_view())

 

6. 메인의 views.py에 Like 상태 확인을 위한 정보를 리스트에 추가

 

7. main.html에서 Like 상태를 확인하여 하트 아이콘 출력 변경되도록 설정

is_like에는 True 혹은 False가 들어있고, True일 경우에는 색이 채워진 하트가 보이고 그렇지 않은 경우 선만 있는 하트가 보이도록 if문으로 작성합니다.