defupdate(self, instance, validated_data): # 중략 info = model_meta.get_field_info(instance)
for attr, value in validated_data.items(): if attr in info.relations and info.relations[attr].to_many: field = getattr(instance, attr) field.set(value) else: setattr(instance, attr, value) instance.save()
return instance
classHyperlinkedModelSerializer(ModelSerializer): # id필드 대신에 url필드를 사용 pass
Validators
장고 기본 validators과 더불어, django-rest-framework에서는 유일성 여부 체크를 도와주는 Validator를 제공해주며, queryset 범위를 제한하여 지정 범위 내에서의 유일성 여부를 체크할 수 있습니다.
UniqueValidator : 지정 필드가 지정 QuerySet범위에서 Unique한지 체크
모델 필드 unique=True 설정에 대응하여, 자동 추가
UniqueTogetherValidator
모델 클래스.Meta.unique_together 속성에 대응하여, 자동 추가
UniqueForDateValidator
모델 필드 unique_for_date=True 설정에 대응하여, 자동 추가
UniqueForMonthValidator
모델 필드 unique_for_month=True 설정에 대응하여, 자동 추가
UniqueForYearValidator
모델 필드 unique_for_year=True 설정에 대응하여, 자동 추가
유효성 검사 예외
rest_framework.exceptions.ValidationError를 기본으로 사용합니다. 이는 응답 상태코드 400으로 처리합니다.
장고 기본에서 제공하는 django.core.exceptions.ValidationError를 사용할 수도 있습니다. 이를 사용하면, rest_framework측 예외로 변환되어 처리됩니다.
Serializer에서 유효성검사 함수 지정하기
Tip: ModelSerializer를 사용하신다면, 유효성 검사 함수는 모델 측에 지정하시는 것이 관리측면에서 좋습니다.
(그렇게 하면 django.admin에서도, api에서도, model자체에서도 유효성검사되므로)
필드 정의 시에 validators인자 지정하기
Field-level 검사 : 특정 필드에 대한 검사
Form에서는 clean_필드명의 함수를 구현하지만, rest_framework에서는 validate_필드명를 구현해줍니다.
함수 인자로 해당 값이 전달됩니다.(value)
DjangoForm과 마찬가지로, 본 함수의 리턴값을 통해 값을 변환할 수도 있습니다.
1 2 3 4 5 6 7
classPostSerializer(serializers.Serializer): title = serializers.CharField(max_length=100)
defperform_create(self, serializer):# CREATE 커스텀은 이 함수를 재정의하세요. serializer.save()
# 생략
classUpdateModelMixin(object): defupdate(self, request, *args, **kwargs): partial = kwargs.pop('partial', False) # 부분 업데이트 여부(patch요청일때임) instance = self.get_object() # 수정할 모델 객체를 획득하고 serializer = self.get_serializer(instance, data=request.data, partial=partial) # Serializer 인스턴스를 만들고 serializer.is_valid(raise_exception=True) # 유효성 검사를 수행합니다. 실패하면 예외발생 !!! self.perform_update(serializer) # DB로의 저장을 수행합니다.
if getattr(instance, '_prefetched_objects_cache', None): # If 'prefetch_related' has been applied to a queryset, we need to # forcibly invalidate the prefetch cache on the instance. instance._prefetched_objects_cache = {}
return Response(serializer.data)
defperform_update(self, serializer):# UPDATE 커스텀은 이 함수를 재정의하세요. serializer.save()