Django REST Framework 사용자 정의 필드 유효성 검사
모델에 대한 사용자 지정 유효성 검사를 생성하여 모델 start_date
이 이전 에 있는지 확인하고 end_date
거의 불가능한 것으로 증명하려고합니다.
내가 시도한 것들 :
내장 Django 유효성 검사기 :이 항목을 확인하지 않습니다.
다음과 같이 내 자신을 작성합니다.
def validate_date(self): if self.start_date < self.end_date: raise serializers.ValidationError("End date must be after start date.")
Serializer 클래스 (및 모델)에 추가 한이 코드는 어느 위치에서도 호출되지 않는 것 같습니다.
또한 사용할 수있는 이 코드를 찾았 지만 방법에 통합하는 방법을 모르겠습니다. 하나의 모델 속성을 확인하는 데 작동하는 것 같지만 두 속성을 확인해야합니다.
내 모델 :
class MyModel(models.Model):
created = models.DateTimeField(auto_now_add=True)
relation_model = models.ForeignKey(RelationModel, related_name="mymodels")
priority = models.IntegerField(
validators = [validators.MinValueValidator(0), validators.MaxValueValidator(100)])
start_date = models.DateField()
end_date = models.DateField()
@property
def is_active(self):
today = datetime.date.today()
return (today >= self.start_date) and (today <= self.end_date)
def __unicode__(self):
...
class Meta:
unique_together = ('relation_model', 'priority', 'start_date', 'end_date')
참고로, 다른 모든 유효성 검사가 작동합니다!
내 시리얼 라이저 :
class MyModelSerializer(serializers.ModelSerializer):
relation_model = RelationModelSerializer
is_active = serializers.Field(source='is_active')
def validate_date(self):
if self.start_date > self.end_date:
raise serializers.ValidationError("End date must be after start date.")
class Meta:
model = MyModel
fields = (
'id', 'relation_model', 'priority', 'start_date', 'end_date', 'is_active'
)
내 견해 :
class MyModelList(generics.ListCreateAPIView):
permission_classes = (IsAdminUser,)
queryset = MyModel.objects.all()
serializer_class = MyModelSerializer
ordering = ('priority')
serializer의 필드가 아니기 때문에 절대 호출 되지 않으므로 개체 전체 유효성 검사 ( validate()
)를 사용해야합니다 . 문서에서 :validate_date
date
class MySerializer(serializers.ModelSerializer):
def validate(self, data):
"""
Check that the start is before the stop.
"""
if data['start_date'] > data['end_date']:
raise serializers.ValidationError("finish must occur after start")
return data
DRF 3.0 이전에는 모델의 깨끗한 기능에 추가 할 수도 있지만 DRF 3.0에서는 더 이상 호출되지 않습니다.
class MyModel(models.Model):
start_date = models.DateField()
end_date = models.DateField()
def clean(self):
if self.end_date < self.start_date:
raise ValidationError("End date must be after start date.")
jgadelange의 대답은 아마도 django rest 3 전에 작동했습니다. django rest framework 3 * 버전을 사용하는 사람이 있다면 이것이 도움이 될 것이라고 생각합니다. 모델 수준에서 검증 프로세스를 유지해야하며 깨끗한 방법이 하나의 솔루션이 될 수 있습니다. 그러나 장고 나머지 프레임 워크 발표는 말한다 여기 사람이 모델 .clean 방법, 검증 나머지 통화하고자하는 경우, 그 / 그녀가 깨끗한 방법은 다음과 같은 방법으로이 시리얼 클래스를 형성 호출 시리얼 라이저의 validate 메소드와 필요를 오버라이드 (override) 할 필요가 있음
(문서가 : clean () 메서드는 serializer 유효성 검사의 일부로 호출되지 않기 때문에)
class MySerializer(serializers.ModelSerializer):
def validate(self, attrs):
instance = MyModel(**attrs)
instance.clean()
return attrs
및 모델
class MyModel(models.Model):
start_date = models.DateField()
end_date = models.DateField()
def clean(self):
if self.end_date < self.start_date:
raise ValidationError("End date must be after start date.")
serializer의 validate()
방법 을 재정의하기로 선택한 경우 상황과 관련하여 여기에 또 다른 대답이 유용 할 수 있습니다 .
Django REST Framework의 Order of Serializer 유효성 검사 에 대한 답변과 관련하여 serializer.validate()
유효성 검사 시퀀스가 끝날 때 메서드가 호출 되었다고 말해야합니다 . 그러나 필드의 유효성 검사기는에, 그 전에라고 serializer.to_internal_value()
제기 ValidationError
끝.
이는 사용자 정의 유효성 검사 오류가 기본 오류와 함께 누적되지 않음을 의미 합니다 .
내 생각에 원하는 동작을 달성하는 가장 깨끗한 방법 은 serializer 클래스에서 대상 필드 메서드 유효성 검사를 사용하는 것입니다 .
def validate_end_date(self, value):
# validation process...
return value
이 경우와 같이 모델에서 다른 필드 값이 필요한 경우 다음을 사용하여 start_date
가져올 수 있습니다 (프로세스가 완료되지 않았기 때문에 아직 검증되지 않음).
# `None` here can be replaced with field's default value
start_date = 'start_date' in self.initial_data
and self.initial_data['start_date'] or None
현장에서 클래스 기반 유효성 검사기로 이것을 구현하는 데 어려움을 겪는 사람을 위해 ...
from rest_framework.serializers import ValidationError
class EndDateValidator:
def __init__(self, start_date_field):
self.start_date_field = start_date_field
def set_context(self, serializer_field):
self.serializer_field = serializer_field
def __call__(self, value):
end_date = value
serializer = self.serializer_field.parent
raw_start_date = serializer.initial_data[self.start_date_field]
try:
start_date = serializer.fields[self.start_date_field].run_validation(raw_start_date)
except ValidationError:
return # if start_date is incorrect we will omit validating range
if start_date and end_date and end_date < start_date:
raise ValidationError('{} cannot be less than {}'.format(self.serializer_field.field_name, self.start_date_field)
당신이 가정 start_date
및 end_date
당신의 시리얼 필드가, 당신이 다음에에서 설정할 수있는 end_date
필드 validators=[EndDateValidator('start_date')]
.
Konrad 답변을 확장하겠습니다. 나는 그것이 매우 명시 적이기 때문에 그것을 좋아하고 또한 우리가 그들을 사용할 때 다른 필드에 대한 유효성 검사를 호출하고 있습니다. 따라서 더 안전하며 중복 될 수 있습니다 (일부 유효성 검사는 두 번 호출 됨).
가장 먼저 주목할 점은 이렇게 구현하면 run_validator를 실행하면 validators 변수에 설정된 유효성 검사 만 나타납니다. 예를 들어 validate_ 메소드를 사용하여 필드의 유효성을 검사하면 실행되지 않습니다.
Also, I have make it inheritable, so we can reimplement the validation function and rehuse the code.
validators.py
from rest_framework.serializers import ValidationError
class OtherFieldValidator:
#### This part is the same for all validators ####
def __init__(self, other_field):
self.other_field = other_field # name of parameter
def set_context(self, serializer_field):
self.serializer_field = serializer_field # name of field where validator is defined
def make_validation(self,field, other_field):
pass
def __call__(self, value):
field = value
serializer = self.serializer_field.parent # serializer of model
raw_other_field = serializer.initial_data[self.other_field] # data del otro campo
try:
other_field = serializer.fields[self.other_field].run_validation(raw_other_field)
except ValidationError:
return # if date_start is incorrect we will omit validating range
#### Here is the only part that changes ####
self.make_validation(field,other_field)
class EndDateValidator(OtherFieldValidator):
def make_validation(self,field, other_field):
date_end = field
date_start = other_field
if date_start and date_end and date_end < date_start:
raise ValidationError('date cannot be')
So the serializer will be like this : serializers.py
# Other imports
from .validators import EndDateValidator
def myfoo(value):
raise ValidationError("start date error")
class MyModelSerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
fields = '__all__'
extra_kwargs = {
'date_end': {'validators': [EndDateValidator('date_start')]},
'date_start': {'validators': [myfoo]},
}
ReferenceURL : https://stackoverflow.com/questions/31278418/django-rest-framework-custom-fields-validation
'program story' 카테고리의 다른 글
Lambda를 사용하는 Java 8 필터 어레이 (0) | 2020.12.30 |
---|---|
Selenium을 사용하여 인증서를 처리하는 방법은 무엇입니까? (0) | 2020.12.30 |
PHP 세션 데이터가 저장되지 않음 (0) | 2020.12.30 |
패턴 매칭 대 스위치 설명 (0) | 2020.12.30 |
불변성이란 무엇이며 왜 걱정해야합니까? (0) | 2020.12.30 |