[DRF] django 요청에 대한 validation과 응답 양식

송민준·2023년 5월 29일
0

출그니 (캡스톤)

목록 보기
4/6

기능 설명

  • validation 요청에 대해 유효한지 확인하는 작업은 필요합니다. 예로 다음과 같은 확인 작업이 있습니다.
    • user_nickname 필드가 50자 넘지 않는지 확인
    • user_nickname이 중복되지 않는지 확인
    • token이 유효한지 확인
  • 응답 양식 여기서 클라이언트 개발자의 요청으로
    {
    "status": "OK",
    "res": [something]
    }
    이런 식으로 모든 요청 종류에 대해 응답 JSON 형식을 지켜야한다.

Serializer에서 Validation

class UserSerializer(serializers.Serializer):
    ...
		def validate_unique_user_nickname(self, value):
        if User.objects.filter(user_nickname=value).exists():
            raise serializers.ValidationError(
                {"status": "ERROR",
                 "res": {"error_name": "닉네임 중복", "error_id": 1}
                 }
            )
        return value
    def validate_unique_user_email(self, value):
        if User.objects.filter(user_email=value).exists():
            raise serializers.ValidationError(
                {"status": "ERROR",
                 "res": {"error_name": "이메일 중복", "error_id": 2}
                 }
            )
        return value
    def create(self, validated_data):
        # 여기서 email 과 nickname validation exception 둘 다 raise 하는 방법을 모르겠음.
        self.validate_unique_user_email(validated_data.get("user_email"))
        self.validate_unique_user_nickname(validated_data.get("user_nickname"))
        ...
    ...

ModelSerializer를 상속해서 시리얼라이저를 생성했다면 건드리지 않아도 될 내용이지만 우리가 원하는 응답 양식에 맞추기 위해 Serializer를 상속했다.

  • validate_unique_user_nickname , validate_unique_user_email : user_nickname과 user_email의 중복을 체크한다. 만약 중복된다면 ValidationError를 raise한다.

‘토큰 생성 에러 응답’을 상속을 통해 수정

토큰을 생성할 당시 토큰에 이상이 있으면 에러코드 “user_not_exists”가 나온다.

이를 응답 양식에 맞게 수정하기 위해 TokenObtainPairSerializer 를 상속했다.

class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
    default_error_messages = {
        "no_active_account": {"status": "ERROR",
                                   "res": {
                                       "error_name": "No active account found with the given credentials",
                                       "error_id": 0
                                   }}
    }
    @classmethod
    def get_token(cls, user):
        token = super().get_token(user)
        token["user_email"]=user.user_email
        token["user_id"]=user.id
        return token
  • default_error_messages : 기본적인 에러 메시지를 커스터마이징 할 수 있다.
    • 우리의 프로젝트에서는 jwt를 생성할 때 요청의 아이디와 비밀번호가 잘못됬을 때의 응답양식을 수정했다.
  • def get_token(cls,user): : 토큰 제공 함수이다.
    • 이를 오버라이딩해서 추가적으로 user_emailuser_id 를 payload 추가했다. 이는 이후에 유저 정보 수정, 삭제, 피드 생성 등에 사용될 예정이다.

‘토큰 인증 에러 응답’을 custom_exception_handler를 통해 수정

우리 프로젝트는 jwt 라이브러리를 사용한다. ValidationError가 raise되면 라이브러리에서 정의된 Error 양식을 따른다. 이는 우리가 수정할 수 없으므로 custom_exception_handler를 이용해서 raise가 발생했을때 응답 양식을 수정했다.

def custom_exception_handler(exc, context):

    if isinstance(exc, AuthenticationFailed):
        return Response({
            'status': 'ERROR',
            'res': {
                'error_name': 'Authentication Failed',
                'error_id': 9
            }
        }, status=401)
    response = exception_handler(exc, context)
    return response
  • if isinstance(exc, AuthenticationFailed): : AuthenticationFailed 에러가 발생했을 때 응답을 정의한다.

그리고 이 exception_handler를 사용함을 알리기 위해 아래를 추가했다.

profile
개발자

0개의 댓글