인증 체계를 설정하는 방법은 아래 두 가지가 있다.
1. settigns.py
에서 전역적으로 설정
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
]
}
APIView
클래스나 @api_view
decorator를 이용하여 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)
이 체계는 토큰 기반 인증 체계를 사용한다. 이 체계를 운영시 사용할 땐 반드시 https에서 사용하라고 한다. 이 체계의 사용은 다음의 단계를 거친다.
setting authentication scheme : rest_framework.authentication.TokenAuthentication
INSTALLED_APPS
:
rest_framework.authtoken
추가
토큰으로 authentication에 성공하면 다음 credentials를 얻을 수 있다.
실패하면 WWW_Authenticate header와 함께 HTTP 401 Unathorized이 응답된다.
이렇게 request.user
나 request.auth
에 접근하여 정상적인 값을 얻을 수 있다는 것은, 추가적인 토큰 serializer를 설정할 필욘 없다고 생각된다. 다만, 원하는 에러메시지가 있거나 토큰을 이용하여 추가적인 validation을 사용할 경우엔 serializer를 구현해도 될 것 같다.
.user
requests.user
은 일반적으로 django.contrib.auth.models.User
객체를 리턴한다.requests.user
의 디폴트 값은 django.contrib.auth.models.AnonymousUser
객체이다..auth
requests.auth
는 추가 인증 컨텍스트를 리턴하는데, 일반적으로 인증된 토큰 객체를 리턴한다.None
이다.DRF에서 Serializers
는
1) BaseSerializer.save()
메서드가 다음 중 하나를 호출.
2) ModelSerialzer.update()
ModelSerializer.update()
가 각각 다음을 호출
3) instance.create()
, instance.save()
.save()
현재 유저, 현재 시각, 혹은 request data에는 포함되어 있지 않은 어떠한 것이라도 attributes를 함께 저장하고 싶을때 추가적인 인수로 .save()
에 넘겨 두면 된다. 예를 들면 아래와 같다.
serializer.save(owner=request.user)
넘겨진 추가적인 attributes는 .save()
가 .create()
, .update()
를 호출할 때 validated_data
에 추가된다.
.save()
예를 들어 .create()
.update()
가 딱히 필요없는 경우 .save()
를 overriding해서 해당 부분을 제거 하는 식으로 코딩할 수 있다.
역직렬화 과정에서 validated data에 접근하려거나, 객체를 save하려고 할때 반드시 선행적으로 .is_valide()
를 호출하라.
데이터가 유효하지 않은 경우 validation errors가 발생하고 이에 대한 예외 처리를 아래와 같이 할 수 있다. 디폴트로 HTTP 400 BAD Request
가 발생된다.
default_error_message
가 나타나는 것이 맞는지.serializer.is_valid(raise_exception=True)
.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
여러개의 필드에 접근해야하는 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
.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 ' 띄어쓰기 반드시 필요하다...!!!
DRF에선 모든 validation은 serializer class에서 이루어진다. Django에선 form, model insta에 부분적으로 나뉘어서 시행된 것과 대조된다.
DRF에는 Django에는 없는 validator 클래스들이 존재한다. 아래와 같은 것들이 존재한다.
UniqueValidator
unuque=True
제약이 필드에 적용되도록 사용된다.UniqueTogetherValidator
UniquForDateValidator
, UniquForMonthValidator
, UniquForYearValidator