DRF API Guide

succeeding·2022년 3월 29일
0

Authentication


Authentication

Setting the authentication scheme

인증 체계를 설정하는 방법은 아래 두 가지가 있다.
1. settigns.py에서 전역적으로 설정

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ]
}
  1. APIView 클래스나 @api_viewdecorator를 이용하여 view단위로 설정
class ExampleView(APIView):
    authentication_classes = [SessionAuthentication, BasicAuthentication]
    permission_classes = [IsAuthenticated]

    def get(self, request, format=None):
        content = {
            'user': str(request.user),  # `django.contrib.auth.User` instance.
            'auth': str(request.auth),  # None
        }
        return Response(content)

API Reference

TokenAuthentication

이 체계는 토큰 기반 인증 체계를 사용한다. 이 체계를 운영시 사용할 땐 반드시 https에서 사용하라고 한다. 이 체계의 사용은 다음의 단계를 거친다.

  1. setting authentication scheme : rest_framework.authentication.TokenAuthentication

  2. INSTALLED_APPS:
    rest_framework.authtoken 추가

토큰으로 authentication에 성공하면 다음 credentials를 얻을 수 있다.

  • request.user will be a Django User instance.
  • request.auth will be a rest_framework.authtoken.models.Token instance.

실패하면 WWW_Authenticate header와 함께 HTTP 401 Unathorized이 응답된다.

이렇게 request.userrequest.auth에 접근하여 정상적인 값을 얻을 수 있다는 것은, 추가적인 토큰 serializer를 설정할 필욘 없다고 생각된다. 다만, 원하는 에러메시지가 있거나 토큰을 이용하여 추가적인 validation을 사용할 경우엔 serializer를 구현해도 될 것 같다.




Requests


Authentication

.user

  • requests.user 은 일반적으로 django.contrib.auth.models.User 객체를 리턴한다.
  • 요청이 인증되지 않은 경우 requests.user의 디폴트 값은 django.contrib.auth.models.AnonymousUser 객체이다.

.auth

  • requests.auth는 추가 인증 컨텍스트를 리턴하는데, 일반적으로 인증된 토큰 객체를 리턴한다.
  • 인증되지 않은 경우나 추가 인증 컨텍스트가 존재하지 않는 경우 디폴트 값은 None이다.



Serializers


DRF에서 Serializers

  1. 직렬화, 역직렬화기능을 한다.
  2. 유효한 데이터로 모델 인스턴스를 저장한다.

Saving instances

logic

1) BaseSerializer.save() 메서드가 다음 중 하나를 호출.
2) ModelSerialzer.update() ModelSerializer.update() 가 각각 다음을 호출
3) instance.create(), instance.save()

Passing additional attributes to .save()

현재 유저, 현재 시각, 혹은 request data에는 포함되어 있지 않은 어떠한 것이라도 attributes를 함께 저장하고 싶을때 추가적인 인수로 .save()에 넘겨 두면 된다. 예를 들면 아래와 같다.

serializer.save(owner=request.user)

넘겨진 추가적인 attributes는 .save().create(), .update()를 호출할 때 validated_data에 추가된다.

Overriding .save()

예를 들어 .create() .update() 가 딱히 필요없는 경우 .save()를 overriding해서 해당 부분을 제거 하는 식으로 코딩할 수 있다.

Validation

역직렬화 과정에서 validated data에 접근하려거나, 객체를 save하려고 할때 반드시 선행적으로 .is_valide()를 호출하라.

Raising an exception on invalid data

데이터가 유효하지 않은 경우 validation errors가 발생하고 이에 대한 예외 처리를 아래와 같이 할 수 있다. 디폴트로 HTTP 400 BAD Request가 발생된다.

궁금한 점 : 예외는 정확히 serializer의 어느 함수의 어느 시점에서 나타나는 것이며, validate를 커스터마이징 했을때 입력한 default_error_message 가 나타나는 것이 맞는지.
serializer.is_valid(raise_exception=True)

Field-level validation

.validate_<field_name> 메소드를 사용하여 field-level validation을 커스터마이징할 수 있다. 형식은 validation error가 있다면 serializers.ValidationError("<error_msg>")를 raise하고 없다면 그 값을 리턴하는 형식이다.

예를 들어, django가 반드시 제목으로 들어가는 블로그 포스팅을 해야한다는 조건이 있다면 다음과 같을 것이다.

class BlogPostSerializer(serializers.Serializer):
	title = seriazliers.CharField(max_length=100)
    
    def validate_title(self, value):
    	if 'django' not in value.lower():
        	raise serialzers.ValidationError("Django에 대한 게시물이 아닙니다.")
        return  value

Object-level validation

여러개의 필드에 접근해야하는 validation이라면 .validate() 메서드를 커스터마이징한다. 이 메서드는 필드값의 딕셔너리만 단 하나의 인자로 갖는다.
아래 예시는 start 시간이 finish 시간 이전인지 검사한다.

class EventSerializer(serializers.Serialzer):
	description = serialzers.CharField(max_length=100)
    start = serialzers.DateTimeField()
    finish = serialzers.DateTimeField()
    
    def validate(self, data):
   		if data['start'] > data['finish']:
        	raise serializers.ValidationError("종료 시각은 반드시 시작 시각 이후여야합니다.")
        return data



Testing


APIClient

Authenticating

.credentials(**kwargs)

authentication headers를 필요로 하는 API를 테스트 할 때, 요청의 headers를 설정해준다.
예시)

from rest_framework.authtoken.models import Token
from rest_framework.test import APIClient

# Include an appropriate `Authorization:` header on all requests.
token = Token.objects.get(user__username='lauren')
client = APIClient()
client.credentials(HTTP_AUTHORIZATION='Token ' + token.key) # 😂 여기서 'Token ' 띄어쓰기 반드시 필요하다...!!!



Validators


DRF에선 모든 validation은 serializer class에서 이루어진다. Django에선 form, model insta에 부분적으로 나뉘어서 시행된 것과 대조된다.

DRF에는 Django에는 없는 validator 클래스들이 존재한다. 아래와 같은 것들이 존재한다.

  • UniqueValidator
    unuque=True 제약이 필드에 적용되도록 사용된다.
  • UniqueTogetherValidator
  • UniquForDateValidator, UniquForMonthValidator, UniquForYearValidator

0개의 댓글