현제의 현재이야기

[KLAE] 0112 개발일지 본문

DRF/KLAE

[KLAE] 0112 개발일지

현재의 현제 2023. 1. 13. 00:03

| 트러블 슈팅

  • 기존 문제점: 세션 로그인으로 진행하면 프론트랑 통신이 안됨. 그래서 jwt 토큰 발급 방식으로 바꿈
  • 토큰이 발급되면 프론트에서 세션 스토리지로 로그인해서 얻은 엑세스 키를 저장
  • 그리고 request 헤더에 토큰을 백으로 넘겨준다.

  • 이렇게 postman에 header key에 Authorization과 로그인해서 얻은 access 키를 넣어서 개발하였음.

user를 토큰 값으로 받아오기

from rest_framework_simplejwt.tokens import AccessToken

def get_token_user(request):
    access_token = AccessToken(request.META.get('HTTP_AUTHORIZATION'))
    user = User.objects.get(pk=access_token['user_id'])
    return user
  • request에서 받은 토큰 값으로 user 뽑아오는 함수를 만듦
  • request.META.get('HTTP_')로 serializer 없이 헤더에서 전송 받은 값을 바로 받을 수 있음!!
  • 이것을 AcessToken함수로 토큰 값을 분석하고 access_token 으로 받음
  • access_token에서 'user_id' 필드를 받아서 user를 받아오고, user 정보를 return 한다. 즉 user = get_token_user(request)를 넣으면 기본의 request.user 와 똑같은 역할을 하는 것

https://github.com/likelion10th-KLAE/server/commit/c158e962df075c9e20bfb5afe234312f5c011d87

 

user를 토큰 값으로 받아오기 · likelion10th-KLAE/server@c158e96

Show file tree Showing 2 changed files with 33 additions and 20 deletions.

github.com

  • 기존의 request.user나 request.user.id 를 다 토큰 처리 함수로 바꾸었다.

좋아요 수정

  • 기존의 좋아요를 누르면 좋아요 카운트만 올라가지 눌렀을 때 내가 눌렀나, 안 눌렀나를 확인할 수가 없었음
  • 그래서 내가 이 게시글에 좋아요를 눌렀으면 하트가 칠해야져야 되는데, 프론트에서 이걸 하길 위해서는 게시글을 누른 user가 해당 게시글을 눌렀는지 true, false값을 뱉어야함.
# 좋아요
@api_view(['GET'])
#@authentication_classes([SessionAuthentication, BasicAuthentication])
#@permission_classes([IsAuthenticated])
def likes(request, pk):
    try:
        user = get_token_user(request)
        post = Post.objects.get(pk=pk)
        if post.like_users.filter(pk=user.id).exists():
            post.like_users.remove(user)
            post.like_num = post.like_users.count()
            post.save(update_fields=['like_num'])
            serializer = LikeUsersSerializer(post)
            res = Response(
                {
                    "like_num" : serializer.data['like_num'],
                    "bool_like_users" : False
                },
                status = status.HTTP_200_OK
            )
            return res
        else:
            post.like_users.add(user)
            post.like_num = post.like_users.count()
            post.save(update_fields=['like_num'])
            serializer = LikeUsersSerializer(post)
            res = Response(
                {
                    "like_num" : serializer.data['like_num'],
                    "bool_like_users" : True
                },
                status = status.HTTP_200_OK
            )
            return res
    except Post.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)
  • get_token_user로 얻은 user정보를 통해서 해당 게시글에 좋아요를 눌렀나 확인하고 만약 user.id가 존재한다면 bool_like_users 값으로 False, 없으면 True를 뱉어줌.
  • res = Response( {"key": "value"} )로 시리얼라이저 없이 json 형식으로 보낼 수 있다!!
  • 또한 시리얼라이저에 담긴 데이터도 key 값을 통해서 얻을 수 있다.

Get One Post 수정

#한 게시물 조회
@api_view(['GET'])
#@authentication_classes([SessionAuthentication, BasicAuthentication])
#@permission_classes([IsAuthenticated])
def get_one_post(request, pk):
    try:
        user = get_token_user(request)
        post = Post.objects.get(pk=pk)
        if post.writer.profile_image:
            profile_image = str(post.writer.profile_image.url)
        else:
            profile_image = "null"
        writer = str(post.writer.username)
        comments = Comment.objects.filter(post__id = pk)

        userplant = UserPlant.objects.get(pk=post.user_plant)
        post.user_plant_name = userplant.name
        post.comment_cnt = comments.count()
        
        date = userplant.created_at.replace(tzinfo=None)
        now = datetime.now().replace(tzinfo=None)
        post.ndate = (now - date).days + 1

        post.save(update_fields=['comment_cnt', 'ndate', 'user_plant_name'])

        if post.like_users.filter(pk=user.id).exists():
            bool_like_users = True
        else:
            bool_like_users = False
        serializer = GetSerializer(post)
        res = Response(
                {
                    "bool_like_users": bool_like_users,
                    "id" : serializer.data['id'],
                    "title" : serializer.data['title'],
                    "give_water" : serializer.data['give_water'],
                    "change_record" : serializer.data['change_record'],
                    "growing_tonic" : serializer.data['growing_tonic'],
                    "like_num" : serializer.data['like_num'],
                    "share" : serializer.data['share'],
                    "photo" : serializer.data['photo'],
                    "comment_cnt" : serializer.data['comment_cnt'],
                    "ndate" : serializer.data['ndate'],
                    "user_plant_name" : serializer.data['user_plant_name'],
                    "body" : serializer.data['body'],
                    "writer": writer,
                    "profile_image": profile_image

                },
                status = status.HTTP_200_OK
            )
        return res
    except Post.DoesNotExist:
        return Response(status = status.HTTP_404_NOT_FOUND)
  • 좋아요만 해결하면 끝나는 것이 아니라 게시글을 누르면 user의 좋아요가 저장 되어있나 안 되어있나 확인해야한다.
  • 그래서 if문을 통해 post.like_users.filter.exist()로 bool 값을 정해주고 bool_like_users 값을 추가하였다.
  • 또한 해당 게시글을 적은 user 프로필과 닉네임을 전해주었어야 해서 만약 post.writer의 프로필 이미지가 있으면 보내준다.

| 트러블 슈팅

  • str(post.writer.profile_image.url)는 post.writer.profile_image만 했을 때, 이미지는 json에 담지 못한다고해서 url로 담아 주었는데, response에는 또 url은 못담기나보다. 그래서 utf-8 인코딩 오류가 나길래 str로 감싸주었더니 오류 없이 잘 되었다.

500에러 해결과 profile 없을 때 오류 뱉던거 해결

if user is not None:
            auth.login(request, user)
            token = TokenObtainPairSerializer.get_token(user)
            refresh_token = str(token)
            access_token = str(token.access_token)
            username = str(user.username)
            if user.profile_image:
                profile = str(user.profile_image.url)
                res = Response(
                    {
                        "user" : serializer.data['email'],
                        "userid": str(user.pk),
                        "username": username,
                        "message" : "로그인 성공!",
                        "profile": profile,
                        "token" : {
                            "access" : access_token,
                            "refresh" : refresh_token,
                        },
                    },
                    status=status.HTTP_200_OK
                )
                return res
            else:
                res = Response(
                    {
                        "user" : serializer.data['email'],
                        "username": username,
                        "userid": str(user.pk),
                        "message" : "로그인 성공!",
                        "profile": "null",
                        "token" : {
                            "access" : access_token,
                            "refresh" : refresh_token,
                        },
                    },
                    status=status.HTTP_200_OK
                )
                return res

        else:
            return Response(status=status.HTTP_400_BAD_REQUEST)
  • 오늘 제일 처음 잡았던 오류인 500 interserver 에러를 로그 봐서 해결
  • 이것도 프로필 문제였는데 The 'profile_image' attribute has no file associated with it.라고 떠서 서버가 안 돌아갔었다.
  • 그래서 if 문을 통해서 user.profile_image가 존재하면 str(user.profile_image.url)를 json에 담아주는 걸로 해결했다.
  • username과 userid 값도 프론트 측에서 요청해서 추가해주었다. 이 또한 user의 값을 통해서 값을 얻고 str()로 감싸주었다.
 

댓글 수정

# 댓글 업로드
@api_view(['POST'])
#@authentication_classes([SessionAuthentication,BasicAuthentication])
#@permission_classes([IsAuthenticated])
def post_comment(request, post_id):
    try:
        user = get_token_user(request)
        serializer = CommentPostSerializer(data=request.data)
        if serializer.is_valid():
            if user.is_authenticated :
                serializer.save(user=user, post_id = post_id, username_comment=user.username)
                return Response(serializer.data, status = status.HTTP_201_CREATED)
  • 저장 될 때 username_comment 값에 username을 불러와 저장하여 코멘트에 닉네임이 보이게 함

| 포스트맨 CSRF 오류 해결법

  • 이렇게 header에 X-CSRFToken 키를 넣고 기존 위에 있던 CSRF 값을 넣으면 해결

| git 강제 pull 커맨드

git fetch --all
git reset --hard origin/master
git pull origin master

| 터미널 관련 커맨드

ssh -i "klae-pem.pem" ubuntu@ec2-3-39-207-4.ap-northeast-2.compute.amazonaws.com

 


| 알게 된 점 및 후기

  • AWS RDS를 통해서 데이터베이스 공유를 하게되면 makemigrations은 한 명만 해도 되고, pull 받은 즉시 migrate만 해주면 된다!!

 오늘 정말 9시간 동안 카페에서 코딩만 하였다. 팀원들과 프론트 측의 오류여도 같이 url을 봐주거나, 넘어 오는 값이 정수인지, null 값인지, 문자열인지 이런 것들을 postman으로 하나하나 해결해가면서 오류를 잡아갔다. 또한 넘어 온 값이 잘못됐거나 필요한 값들이 더 없는지 지속적으로 소통하는 것이 중요했다. 못 한다는 방어적인 자세가 아니라 다 잡을 수 있다는 강한 생각이 오늘 만드는 서비스를 진화시켜주었다. 그리고 구글링은 정말 중요하다. 정말 정말로.. 모든 것을 알고있다.

'DRF > KLAE' 카테고리의 다른 글

[KLAE] 최종 발표회 후기  (2) 2023.01.15
[KLAE] 0113 개발일지  (0) 2023.01.14
[KLAE] 0110 개발일지  (0) 2023.01.10
[KLAE] 0107 개발일지  (0) 2023.01.07
[KLAE] 0106 개발일지  (0) 2023.01.06
Comments