[drf]airbnb-api -11 MeView & user_detail

Hyeseong·2021년 3월 26일
0

project 디렉토리 url설정

users앱을 더하여서 API와 url 연결로 넘어가도록 했어요.

...
urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/v1/rooms/', include('rooms.urls')),
    path('api/v1/users/', include('users.urls')),
]
...

user API url

users/urls.py

from django.urls import path
from . import views

app_name = "users"

urlpatterns = [
    path('me/', views.MeView.as_view()),# 나의 계정 정보
    path('<int:pk>/', views.user_detail), # 다른 유저의 정보
]

user API - MeView

본인의 계정정보를 확인하고 수정하는 API를 작성 해볼게요.

필요한 것들을 임포트 해줍니다. APIView로 작성하니 관련 된 것들을 상단에 일단 깔아 둘게요.

이번에 정말 중요한 녀석중에 하나인데요. permission_classes APIView를 사용하게 되면 쓸수 있는 카드중 하나에요. 클래스에 어떤 허가?를 준다는 말일까요?

뺑뻉 돌려 얘기했는데 로그인한 상태일 경우 해당 API, MeView클래스에 접근 가능하다는 소리에요.

users/views.py

from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated #  인증한 유저만 해당 메소드에 접근 가능하도록함.
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 ReadUserSerializer, WriteUserSerializer


class MeView(APIView):

    permission_classes = [IsAuthenticated] # 인증된 유저만 접근 가능

    def get(self, request):
        return Response(ReadUserSerializer(request.user).data) # stats 키워드가 없으면 기본값으로 200을 뱉어네요.

    def put(self, request):
        serializer = WriteUserSerializer(request.user, data=request.data, partial=True)
        # partial=True옵션 안쓰면 PUT메서드 사용시 하나 혹은 전체가 아닌 일부만 달랑 보내면 오류발생.
        if serializer.is_valid():
            serializer.save()
            return Response()
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQEUST)

@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)

user API - serializer

기존 Serializer 클래스를 상속 받은 UserSerializer를 ModelSerializer로 상속받고 이름도 RelatedUserSerializer로 변경할게요.

RelatedUserSerializer의 목적은 관계를 맺어서 정보를 표현하기 위한 용도로 일단 만들게요.
그렇 해당 관련은 방을 등록한 Host의 정보와 연결하는거에요.

즉, 아래에 ReadRoomSerializer 클래스 변수에서 사용하게 만들어서 중첩 시리얼라이저로 쓰는거조.

# rooms/serializers.py
...
from users.serializers import RelatedUserSerializer

class ReadRoomSerializer(serializers.ModelSerializer):

    user = RelatedUserSerializer()

    class Meta:
...

반면에 ReadUserSerializer는 비밀번호까지 있는 만큼 유저의 더 프라이빗한 정보까지 보여주도록 하는 용도로 만들게요.

user/serializers.py

기존 room API에서 RoomSerializer를 Serializer로 작성해서 뚱뚱했는데요. 날씬하고 편리하게 만들어주기 위해 모두 아래와 같이 ModelSerializer를 상속 받아서 작성할게요.

from rest_framework import serializers
from .models import User


class RelatedUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = (
            'username',
            'first_name',
            'last_name',
            'email',
            'avatar',
            'superhost',
        )


class ReadUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        exclude = (
            'groups',
            'user_permissions',
            'password',
            'last_login',
            'is_superuser',
            'is_staff',
            'is_active',
            'date_joined',
        )


class WriteUserSerializer(serializers.ModelSerializer): 
    class Meta:
        model = User
        fields = ('username', 'first_name', 'last_name', 'email') # Profile을 변경할때 사용할 API에 사용

    def validate_first_name(self, value):
        print(value)
        return value.upper() # 특정필드를 오버라이딩하여 사용할 수 있음

room/serializer.py

기존 엄청나게 길었던 녀석인WriteUserSerializer는 ModelSerializer를 상속 받아 작성할게요.
메타클래스를 작성해서 Room클래스를 model에 넣어주고
exclude 메타클래스 변수를 작성해서 4개 빼고 모두 나타나도록 만들어 줄게요.

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 = ("modified",)


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
profile
어제보다 오늘 그리고 오늘 보다 내일...

0개의 댓글