본문 바로가기

개발/장고

[해설과 함께 읽는 DRF 문서] Validation

반응형

데이터를 역직렬화 할 때, 유효성이 보장된 데이터에 접근 하거나, 객체 인스턴스를 저장하기 전에 is_valid() 호출하는 것은 필수이다.

serializer = CommentSerializer(data={'email': 'fooboar', 'content': 'baz'})
serializer.is_valid()
# False
 
serializer.errors
# {'email': ['Enter a valid e-mail address.'], 'created': ['This field is required.']}

각각의 key는 필드 이름이고, 각 values 는 필드에 해당하는 에러메세지에 대한 리스트 이다. non_field_errors key는 일반적인 validation 에러들에 대해서 보여질 수 있다. non_field_errors key의 이름은 NON_FIELD_ERROS_KEY 를 이용해서 커스텀 할 수 있다.

리스트의 item을 역직렬화 할 때, 에러는 역직렬화된 아이템 각각을 보여주면서, 딕셔너리의 리스트로 리턴 될 수 있다.


설명

  1. 위 설명에서 유효성이 보장된 데이터에 접근 하거나 의 의미는 serializer.data 로 유효성 검사가 완료된 데이터에 접근하는 것으로 볼 수 있다. 즉, serializer.data 를 호출하려면, 이전에 is_valid() 가 선행 되어야 한다.
  2. 객체 인스턴스를 저장하기 전 상황은, 내부 DB에 외부로 부터 들어온 값을 저장하기 위해서 is_valid() 가 선행되어야 함을 말한다. 이는 흔히 create 혹은 update 동작에 대해서 외부로 부터 전해져온 데이터의 유효성 검사가 완료되어야만 데이터를 생성하고 업데이트를 하는 것과 같은 맥락에서 이해할 수 있다.
  3. 만약에 serializer.is_valid() 과정에서 에러가 발생했다면, serializer.erros 를 통해서 어떤 에러가 발생하였는지 확인할 수 있다.
  4. non_field_errors 는 위의 설명만 보아서는 어떤 경우에 발생하게 되는지 명확하지 않은데, 필드와 관련된 validation 에러가 아닌 경우에 발생한다. 아래와 같은 경우에 발생할 수 있다.
class UserSerializer(serializers.ModelSerializer):
    def validate_password(self, value):
        if value.isalnum():
            raise serializers.ValidationError('password must have atleast one special character.')
        return value
    def validate(self, data):
        if data['first_name'] == data['last_name']:
            raise serializers.ValidationError("first_name and last_name shouldn't be same.")
        return data
    class Meta:
        model = User
        fields = ('username', 'email', 'first_name', 'last_name', 'password')
        extra_kwargs = {
            'password': {'write_only': True}
        }`

In [10]: data = {'first_name': 'john', 'last_name': 'john', 'username': 'john', 'password': 'abc123#'}
In [12]: serializer = UserSerializer(data=data)
In [13]: serializer.is_valid()
Out[13]: False
In [14]: serializer.errors
Out[14]: {'non_field_errors': [ErrorDetail(string="first_name and last_name shouldn't be same.", code='invalid')]}`
반응형