코딩,해볼까

05.11. [술술술_project. 4] MyPage 작업 (2) 본문

Back/TIL

05.11. [술술술_project. 4] MyPage 작업 (2)

떠굥 2023. 5. 11. 23:05

0.  오늘의 프로젝트 작업


Tutorial 1: Serialization

Creating a Serializer class

 

ProfileView의 put, delete 작업

- put : 프로필 수정 + 비밀번호 수정과 해싱

- delete : 회원탈퇴

 

아래 RESTframework 기본 코드를 통해 오늘의 작업 방향을 설정하고 오류를 해결할 수 있었다.

    def update(self, instance, validated_data):
        """
        Update and return an existing `Snippet` instance, given the validated data.
        """
        instance.title = validated_data.get('title', instance.title)
        instance.code = validated_data.get('code', instance.code)
        instance.linenos = validated_data.get('linenos', instance.linenos)
        instance.language = validated_data.get('language', instance.language)
        instance.style = validated_data.get('style', instance.style)
        instance.save()
        return instance

snippet 은 작은 부분이라는 뜻으로 재사용이 가능한 이라는 프로그래밍 용어이다.


1.  문제점

포스트맨으로 프로필 수정 테스트를 거치면서 기본 user 모델에서 필수로 선택해둔 필드들을 정확하게 채우지 않으면 수정이 제대로 이루어지지 않고 자꾸 에러를 뱉었다.

 

 

 


2. 시행착오

처음에는 게시글 수정과 유사~ 동일하게 하면 될 것이라고 생각했다.

   user = get_object_or_404(User,id=user_id)
        if request.user.id == user.id:
            serializer = UserProfileSerializer(data=request.data)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data, status=status.HTTP_200_OK)
            else:
                return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        else:
            # 프론트에서 수정 버튼이 아예 노출되지 않도록 할 예정
            return Response("본인만 접근 가능합니다.", status=status.HTTP_403_FORBIDDEN)

문제는 포스트맨에서 field 중에 꼭 들어가야만 하는 항목들이 있다는 오류를 자꾸만 뱉는 것이었다.

class UserProfileSerializer(serializers.ModelSerializer):
    followers = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
    my_articles = ArticleListSerializer(many=True)
    like_articles = ArticleListSerializer(many=True)

    class Meta:
        model = User
        fields = ("id", "nickname", "profile_img", "password",
                  "fav_alcohol", "amo_alcohol", "followings","followers","like_articles", "my_articles")
        
        # "followers", "my_articles","like_articles"

 

UserProfileSerializer 의 상태는 위와 같았고, my_articles, like_articles 가 꼭 들어가야 한다는 오류를 뱉어 

UserProfileEditSerializer 를 새로 생성하여 같은 작업을 반복하였으나, 이도 다른 항목들 중 꼭 들어가야 하는 항목이 있다는 오류를 동일하게 뱉었다.

class UserProfileEditSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ["user_id","nickname","profile_img","fav_alcohol", "amo_alcohol","password"]
        extra_kwargs = {
            "user_id": {
                "read_only": True,
            },
        }

views.py도 계속 수정해봤으나.. 이 문구를 없앨 수가 없었다.

 def put(self, request, user_id):
        """
        프로필 수정
        """
        # serializer = UserSerializer(data=request.data)
        # myInfo = User.objects.get(id=user_id)
        user = get_object_or_404(User,id=user_id)
        serializer = UserProfileEditSerializer(user, data=request.data)
        # print(request.data)
        if serializer.is_valid(raise_exception=True):
            serializer.save() 
            return Response(serializer.data, status=status.HTTP_200_OK)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

3. 해결방법

serializers에서 사용할 수 있는 create, update 함수가 있는데, 이를 사용할 수 있다고 팀원에게 정보를 얻었다.

     def update(self, instance, validated_data):
         return super().update(instance, validated_data)

자동완성을 해주는 기본 코드 형태이다.

 def create(self, validated_data):
        password = validated_data.pop("password")
        user = User(**validated_data)
        user.set_password(password)
        user.save()
        return user

위 코드는 create 함수인데, password를 pop으로 따로 가져와서 해싱해주는 방식으로 기본 회원가입 시 사용하는 함수이다. 이 코드를 UserProfileEditSerializer 와 섞어보면 어떨까? 라고 생각했다.

    # instance = database
    def update(self, instance, validated_data):
        password = validated_data.pop("password")
        instance.set_password(password) # 해싱
        instance.save() # 데이터베이스에 저장
        return instance

다양한 시도 끝에 정상적으로 작동하는 코드를 찾았다! 위 user를 instance로 바꿔주었더니 잘 작동했다.

update 함수의 2번째 인자인 instance가 어떤 의미인지 몰라서 더 어려웠다.

   instance = database
    def update(self, instance, validated_data):
        print(instance) #email
        print(instance.email) #email
        print(instance.id) 
        print(instance.nickname) 
        print(instance.age) 
        password = validated_data.pop("password")
        instance = User(**validated_data)
        instance.set_password(password) # 해싱
        instance.save() # 데이터베이스에 저장
        return instance

print로 계속해서 찍어봤는데, instance는 이메일을 보여줬다. 

코드를 눌러서 팀원과 함께 이 instance에 대해 파고파고 들어가며 이해해보려고 했지만.. 뭔가 명확한 코드를 찾지 못했다.

시리얼라이저의 기본 로그인 틀이 email 이라서일까?..

코드는 정상적으로 작동하니 다음에 더 공부해보기로 했다.

        instance.nickname = validated_data.get('nickname', instance.nickname)
        instance.profile_img = validated_data.get('profile_img', instance.profile_img)
        instance.fav_alcohol = validated_data.get('fav_alcohol', instance.fav_alcohol)
        instance.amo_alcohol = validated_data.get('amo_alcohol', instance.amo_alcohol)

이후에 내가 수정하게끔 하고싶은 정보들을 가져와서 instance.으로 가져와서 업데이트를 할 수 있게 만들어줬다.

연결되어있는 views.py도 아래 첨부한다.

    def put(self, request, user_id):
        """
        프로필 수정
        """
        user = get_object_or_404(User,id=user_id)
        serializer = UserProfileEditSerializer(user, data=request.data)

        if serializer.is_valid(raise_exception=True):
            serializer.save() 
            return Response(serializer.data, status=status.HTTP_200_OK)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

serializer.save()가 실행되는 시점에 serializers.py의 update 함수가 실행된다.


4. 알게된 점

serializers에는 사용할 수 있는 기본 함수인 create와 update가 있다.

사용하는 방법은 공식문서에도 설명이 잘 되어 있다.

공식 문서에 나와있는 기본 코드와 설명들을 잘 활용하면 지금 단계에서는 무엇이든 만들 수 있다.

내게는 큰 문제일지 몰라도 팀원들과 함께하면 금방 풀 수 있다.

 

 

 

 

 

 

 

 

 

Comments