7π
I ran into a similar problem where my custom validation field was not being called. I was writing it to bypass an incorrect DRF validation (more details shown below, but not necessary for the answer).
Looking into the DRF source code I found my problem: DRF always validates your field using its code before validating with your custom code.
''' rest-framework/serializers.py '''
for field in fields:
validate_method = getattr(self, 'validate_' + field.field_name, None)
primitive_value = field.get_value(data)
try:
# DRF validation always runs first!
# If DRF validator throws, then custom validation is not called
validated_value = field.run_validation(primitive_value)
if validate_method is not None:
# this is your custom validation
validated_value = validate_method(validated_value)
except ValidationError as exc:
errors[field.field_name] = exc.detail
except DjangoValidationError as exc:
errors[field.field_name] = get_error_detail(exc)
Answer: Custom validators cannot be used to bypass DRFβs validators, as they will always run first and will raise an exception before you can say it is valid.
(for those interested, the validation error I hit was like this: ModelSerializer used for ModelA, which has a OneToOne relation to ModelB. ModelB has a UUID for its pk. DRF throws the error '53abb068-0286-411e-8729-0174635c5d81' is not a valid UUID.
when validating, which is incorrect, and really infuriating.)
5π
Your ParentSerializer validation method has some issues. Assumes that there is a title
field in your ParentSerializer
model. For field level validation, you will get the field instead of whole data. That is validate_title
function should have title
(title field of the data) as parameter not data
. So you dont have to check data.get('title')
for the existance of title
. Reference
class ParentSerializer(serializers.ModelSerializer):
"""
Serializer for task
"""
def validate_title(self, title):
if not title:
raise serializers.ValidationError('Please set title')
return title
- Django-rest-framework : list parameters in URL
- Nested loop in Django template
- Django: Implementing a referral program
- Setting a cookie in Django Rest Framework API
- How do I use request.META.get('HTTP_REFERER') within template?
1π
In addition to @sean.hudsonβs answer I was trying to figure out how to override the child serializer validation.
It might be possible to "skip" or more accurately ignore children serializer validation errors, by overriding to_internal_value
of the ParentSerialzer:
class ParentSerializer(serializers.ModelSerializer):
children = ChildSerializer(many=True)
def to_internal_value(self, *args, **kwargs):
try:
# runs the child serializers
return super().to_internal_value(*args, **kwargs)
except ValidationError as e:
# fails, and then overrides the child errors with the parent error
return self.validate(self.initial_data)
def validate(self, attrs):
errors = {}
errors['custom_override_error'] = 'this ignores and overrides the children serializer errors'
if len(errors):
raise ValidationError(errors)
return attrs
class Meta:
model = Parent
- Django : Static content not found
- Docker Django could not connect to server: Connection refused
- Differentiating between different post requests on the same page in Django views.py
- Nginx location path with proxy_pass
- Performing non-blocking requests? β Django
1π
My problem was that I had my own custom to_internal_value
method. Removing it fixed the issue.
class EventSerializer(serializers.Serializer):
end_date = serializers.DateTimeField(format=DATE_FORMAT, required=True)
start_date = serializers.DateTimeField(format=DATE_FORMAT, required=True)
description = serializers.CharField(required=True)
def validate_start_date(self, start_date):
return start_date
def validate_end_date(self, end_date):
return end_date
# def to_internal_value(self, data):
# if data.get('start_date', False):
# data['start_date'] = datetime.strptime(data['start_date'], DATE_FORMAT)
# if data.get('end_date', False):
# data['end_date'] = datetime.strptime(data['end_date'], DATE_FORMAT)
# return data
- Amazon + Django each 12 hours appears that [Errno 5] Input/output error
- Django admin β group permissions to edit or view models
1π
I would like to add what the official documentation says, I hope it can be of help.
Field-level validation
You can specify custom field-level validation by adding .validate_<field_name> methods to your Serializer subclass. These are similar to the .clean_<field_name> methods on Django forms.
These methods take a single argument, which is the field value that requires validation.
Your validate_<field_name> methods should return the validated value or raise a serializers.ValidationError. For example:
from rest_framework import serializers
class BlogPostSerializer(serializers.Serializer):
title = serializers.CharField(max_length=100)
content = serializers.CharField()
def validate_title(self, value):
"""
Check that the blog post is about Django.
"""
if 'django' not in value.lower():
raise serializers.ValidationError("Blog post is not about Django")
return value`
- SSH into Django Shell
- What cheat sheets exist for Django?
- Django REST Framework different depth for POST/PUT?
- Docker Django could not connect to server: Connection refused