[drf | endpoint] Build a Backend REST API - 28

Hyeseong·2021년 3월 5일
0

Add manage user endpoint👩‍🌾

Build a Backend REST API - 27에서 test 코드를 짜봤는데요. 실제로 view짜볼게요.


Before Beginning👨‍🍳

현재는 serializer.py파일에는 UserSerializer 클래스가 있는데요.

여기에 update()메소드를 작성하여 user객체를 업데이팅 되도록 할거에요.

또 views.py 파일에는 generics 모듈의 RetrieveUpdateAPIView클래스를 상속받아 클래스를 짜보도록 할게요.

시작👩‍🍳

user/views.py 파일 첫째줄에 authentication, permission를 입력할게요. 인증인가에 관련한 부분이에요.

RetrieveUpdateAPIView를 상속받아 클래스 ManageUserView 만들게되는데요. 부모클래스 이름이 빡! 느낌오조. 읽기와 수정에 특화된 API라는점!

우리가 구현할 endpoint에 인증과 인가 기능이 있어야 하므로authentication_classes, permission_classes를 정의하도록 할게요.

views.py👨‍🔧

from rest_framework import generics, authentication, permission

...
...
...

class ManageUserView(generics.RetrieveUpdateAPIView):
   """Manage the authenticated user"""
   serializer_class = UserSerializer
   authentication_classes = (authentication.TokenAuthentication,) # cookie , Token 등등
   permission_classes = (permissions.IsAuthenticated,)   # 등록된 유저만 접근할수 있도록함

   # retrieve and return authenticated user
   # this method is also required for update (patch)
   def get_object(self):
       """Retrieve and return authentication user"""
       return self.request.user

serializers.py👨‍🏭

create()메서드 아래에 update()메서드를 정의할게요
눈여겨 볼 만한 것들이 몇개 있는데요.

  • pop()메서드 리스트의 메서드가 아닌 딕셔너리의 메서드에요. 키워드에 해당하는 키-벨류를 지워버리거나 만약 해당 키가 없다면 None을 반환해요.
  • super() 메서드는 ModelSerializer's의 update를 사용할 수 있게 작동해요.
  • 여기서 pop()메서드를 처음 넣어서 약간 커스터마이징한 것을 제외하고는 super()메서드를 사용해서 기본 기능을 그대로 사용하게되요.
class UserSerializer(serializers.ModelSerializer):
    """Serializer for the users object"""

    class Meta:
        model = get_user_model()
        fields = ('email', 'password', 'name')
        extra_kwargs = {'password': {'write_only' : True, 'min_length': 5}}
    
    def create(self, validated_data):
        """Create a new user with encrypted password and return it"""
        return get_user_model().objects.create_user(**validated_data)

    def update(self, instance, validated_data):
        """Update a user, setting the password correctly and return it"""
        password = validated_data.pop('password', None) # delete the 'password' key in dict if it exists or return None
        user = super().update(instance, validated_data)

        if password:
            user.set_password(password)
            user.save()
        return user

urls.py👨‍💼

 from django.urls import path

from user import views

app_name = 'user'

urlpatterns = [
...
...
    path('me/', views.ManageUserView.as_view(), name='me'), # new
]

TEST~👨‍🔬

이번에는 성공했어요~

❯ docker-compose run --rm app sh -c "python manage.py test"
Starting recipe-app-api2_db_1 ... done
Creating recipe-app-api2_app_run ... done
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
...Waiting for database...
Database unavailable, waiting 1 second...
Database unavailable, waiting 1 second...
Database unavailable, waiting 1 second...
Database unavailable, waiting 1 second...
Database unavailable, waiting 1 second...
Database available!
.Waiting for database...
Database available!
...............
----------------------------------------------------------------------
Ran 19 tests in 1.481s

OK
Destroying test database for alias 'default'...

modeheader🤠

정말 괜찮은 크롬 익스텐션 하나 소개해드릴 건데요.
modheader라고 해요. 가볍게 익스텐션 설치해주세요.
특히 header부분을 수정하는걸 간편하게 해줘요.

만약 docker-compose up -> 127.0.0.1:8000/api/create/ -> ../token/ -> .../me/ url로 가기 위해선 중간에 발급 받은 토큰을 다운받은 modeheaders 익스텐션을 실행해서 header부분의 authentication을 선택하고 value값에는 token 토큰값 이렇게 넣어줄게요. 중간에 띄워쓰기 공백이 있다는점! 놓치지 마세요.

느낀점👲

기본 장고에서 제공하는 validation기능들과 django restframework의 인증, 인가 기능들에 대한 이해가 있어야 끌어다가 어느 시점에 적절히 사용하고 이를 커스터마이징하여 이용할 수 있을 것 같다는 생각이 든다. 단순히 그냥 따라한다기 보단?!
왜?! 이걸 사용하는지에 대한 더 한차원 깊은 생각이 있어야 상황에 따라 유연히 대응할 수 있을 것 같다.

profile
어제보다 오늘 그리고 오늘 보다 내일...

0개의 댓글