본문 바로가기

프로그래밍/Django개발(MAC OS)

Django Rest API 서버 만들기 요약 - Day 3

반응형

이번에는 USER의 데이터를 가져와 보도록 할 것입니다.

 

유저 데이터는

1. 내 프로필과

2. 다른 상대방의 프로필을 볼 수 있을 것입니다. 

나의 프로필은 현재 접속한 나 자신의 값을 가져오면 되기 때문에 별도의 pk값 USER의 ID값이 필요없지만, 상대방의 경우에는 USER의 ID값이 필요하죠? 

이런 방식으로 아래 View파일을 만들어 봅니다

#users/views.py


from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework.views import APIView
from rest_framework import status
from .models import User
from .serializers import RelatedUserSerializer


class MeView(APIView):
    def get(self, request):
        if request.user.is_authenticated:
            return Response(ReadUserSerializer(request.user).data)

    def put(self, request):
        pass


@api_view(["GET"])
def user_detail(request, pk):
    try:
        user = User.objects.get(pk=pk)
        return Response(ReadUserSerializer(user).data)
    except User.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

 

우선 인증을 하기 위해서 Django RestFramework의 인증 부분을 사용하면 엄청 간편하게 구현할 수 있습니다.

from rest_framework.permissions import IsAuthenticated

class MeView(APIView):
    permission_classes = [IsAuthenticated]
    ...

이런 형태로 permission_class만 해주면 인증 부분은 자동으로 처리해줍니다.

 

 

다음은 업데이트를 해주기 위해서 WriteSerializer를 만들어주도록 할 것입니다.
이번에는 ModelSerializer를 사용했고, ModelSerializer를 사용하면 아주 간편하게 처리를 해줄 수 있습니다.

ModelSerializer를 사용해도 Validation을 할 수 있는데, 이는 함수명(self, value): 값을 가지고 하면되는데 반드시 Return데이터는 value의 값을 그래도 리턴해주어야 한다는 점입니다.

#users/serializers.py

class WriteUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ("username", "first_name", "last_name", "email")

    def validate_first_name(self, value):
        print(value)
        return value.upper()

Serializer를 만들었으니 이제 view를 업데이트 해주면됩니다.

#users/views.py

class MeView(APIView):

    permission_classes = [IsAuthenticated]

    def get(self, request):
        return Response(ReadUserSerializer(request.user).data)

    def put(self, request):
        serializer = WriteUserSerializer(request.user, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response()
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

 

 


아래 코드를 보면 RoomSerializer가 Read,와 Write 두가지가 있는 걸 확인할 수 있는데, Read의 경우는 User의 값을 나타내야 하므로 예를들어 User가 SuperUser인지를 알아야 하기 때문에 User에 대한 정보가 필요하면 ReadRoomSerializer 필요없고 업데이트만을 할 경우에는 WriteRoomSerializer를 사용했는데

ModelSerializer를 사용하면 이 두가지를 합 칠 수 있다.

from rest_framework import serializers
from users.serializers import RelatedUserSerializer
from .models import Room


class ReadRoomSerializer(serializers.ModelSerializer):

    user = RelatedUserSerializer()

    class Meta:
        model = Room
        exclude = ()


class WriteRoomSerializer(serializers.ModelSerializer):
    class Meta:
        model = Room
        exclude = ("user", "modified", "created")

        def validate(self, data):
            if self.instance:
                check_in = data.get("check_in", self.instance.check_in)
                check_out = data.get("check_out", self.instance.check_out)
            else:
                check_in = data.get("check_in")
                check_out = data.get("check_out")
                if check_in == check_out:
                    raise serializers.ValidationError("Not enough time between changes")
            return data

 


 

 

사용자 페이지에 가게되면 좋아요한 콘텐츠를 볼 수 있도록 되어 있지만, 일반적으로 좋아요한 것들이 1000개가 넘어가면 복잡해 지기 떄문에 별도의 favs를 나타내는 URL을 만드는 것이 좋다.

그렇게 하기 위해서 FavsVIew를 만들자.

#users/views.py

class FavsView(APIView):

    permission_classes = [IsAuthenticated]

    def get(self, request):
        user = request.user
        serializer = RoomSerializer(user.favs.all(), many=True).data
        return Response(serializer)

    def put(self, request):
        pk = request.data.get("pk", None)
        user = request.user
        if pk is not None:
            try:
                room = Room.objects.get(pk=pk)
                if room in user.favs.all():
                    user.favs.remove(room)
                else:
                    user.favs.add(room)
                return Response()
            except Room.DoesNotExist:
                pass
        return Response(status=status.HTTP_400_BAD_REQUEST)

위 코드에서 put 함수를 보면, fav값이 있으면 그 값을 지우고, 없으면 방을 추가하는 개념입니다.

 


이제 회원을 만드는 방법에 대해서 한번 알아보도록 하겠습니다.

먼저 회원 등록을 하기 위해서 Serializer에서 UserSerializer를 만들어줍니다.  앞서 했던 것처럼 read_only_field를 만들어줍니다.

 

회원 가입에서 다른 POST방식과 다른 부분은 비밀번호입니다. 비밀번호의 경우에는 serializer에 노출해서도 안되기 떄문에 먼저 password를 write_only로 설정하면 Serializer에서 나타나지 않게 됩니다.

그리고 장고에서는 password를 반드시 set_password()함수를 통해서 암호화 해서 저장을 해야만합니다.

그래서 ModelSerializer에서 cretate()함수를 오버라이딩해서 validate에서 password를 바꿔주고 저장을 해야 하는 것이죠
        user = super().create(validated_data) 를 하면 instance가 반환되는데 그 인스턴스에 setpassword를 하는 개념이라고 보시면 됩니다.


class UserSerializer(serializers.ModelSerializer):

    password = serializers.CharField(write_only=True)

    class Meta:
        model = User
        fields = (
            "id",
            "username",
            "first_name",
            "last_name",
            "email",
            "avatar",
            "superhost",
            "password",
        )
        read_only_fields = ("id","superhost","avatar")

    def create(self, validated_data):
        password = validated_data.get("password")
        user = super().create(validated_data)
        user.set_password(password)
        user.save()
        return user

 

그럼 내일은 로그인 JWT에 대해서 알아보도록 하겠습니다.

반응형