Issue
Let's say I have the following serializers:
class AnswerSerializer(ModelSerializer):
answer_text=CharField()
def validate_answer_text(self, value):
...
return value
def validate(self, value):
...
return value
class QuestionSerializer(ModelSerializer):
question_text=CharField()
answer=AnswerSerializer(many=True, read_only=False)
def validate_question_text(self, value):
...
return value
def validate(self, value):
...
return value
If validate_answer_text
or validate
in AnswerSerializer
or validate_question_text
in QuestionSerializer
raise a ValidationError
, the validate
of QuestionSerializer
won't be run. Thus, I cannot explain all the problem of the POST data.
Is there a way to run the validate
function of a serializer even if one of it's field validator or children serializer validation failed and then combine all the errors ?
I have tried the following but did not succeed make it work properly. It does run both validate function and other validators but you cannot nest AllErrorSerializer and more importantly, it does not work when you do not have error: you can't save instance because you have inspect serializer.data.
EDIT
Due to Willem Van Onsem answer, I ended up with the following solution:
#serializers.py
class AnswerSerializer(ModelSerializer):
answer_text=CharField()
class Meta:
model=Answer
...
def validate_answer_text(self, value):
...
return value
def validate(self, value):
...
return value
class QuestionSerializer(ModelSerializer):
question_text=CharField()
answer=AnswerSerializer(many=True, read_only=False)
class Meta:
model=Question
...
def validate_question_text(self, value):
...
return value
class BasicAnswerSerializer(ModelSerializer):
answer_text=CharField()
class Meta:
model=Answer
...
class BusinessRuleValidator(ModelSerializer):
question_text=CharField()
answer=BasicAnswerSerializer(many=True, read_only=False)
class Meta:
model=Question
...
def validate(self, value):
...
return value
#views.py
class QuestionViewSet(ModelViewSet):
...
def create(self, request):
validator = BusinessRuleValidator(data=request.data)
validator.is_valid()
serializer = QuestionSerializer(data=request.data)
serializer.is_valid()
if (len(validator.errors) or len(serializer.errors)):
return Response(merge(validators.errors, serializer.errors), status=404)
serializer.create()
return Response('created', status=201)
Solution
It makes no sense to run validate when of of the fields is invalid. Django will first validate the individual fields, and then construct a dictionary that contains the validated data and thus run the .validate(…)
method with that validated data.
But since the data of (at least) one of the fields is invalid, thus thus means that we can not construct such dictionary if valid data, and therefore the precondition of the .validate(…)
method no longer holds. In order to fix this, first these fields should be available.
For example your serializer might have a boolean field. If a value tralse
is for example passed to that field, and the field requires to be true
or false
, then what value should be passed for that field? A random boolean, the string tralse
?
Another field validator can simply require that the field is part of the request. This thus means that if that field validator fails, there is simply no value for that field. So the only sensical thing to do might be to omit it from the validated_data
dictionary, but the validate
method takes as precondition that all required fields are in the validated_data
dictionary. It thus again makes no sense to run validate
on that data.
Answered By - Willem Van Onsem
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.