'Get value of another field in Field level Validation in DRF
I am using Field level Validation in my serializer and I have situation where I need value of first field while validating second field. I know in object level validation I can have access to that but my serailzer have many=True and in object level validation I cannot tell client side which iteration have raised the error.
Serailzer :
class Keys_Serializer(serializers.Serializer):
"""
"""
key_id = serializers.IntegerField(required=True)
key_name = serializers.CharField(required=True)
value_id = serializers.IntegerField(required=False)
def validate_key_id(self, value):
"""
validate key id
"""
*** validate key_id here ***
return value
def validate_value_id(self, value):
"""
validate value_id w.r.t key_id
"""
*** I need key_id of current iteration here so that I can validate value_id. ***
return value
Is there any way of accessing the value of key_id in value_id validation.
Solution 1:[1]
I dug around codebase of drf a little bit. You can get values of all fields using following approach. This way you can throw serialization error as {'my_field':'error message} instead of {'non_field_error':'error message'}
def validate_myfield(self, value):
data = self.get_initial() # data for all the fields
#do your validation
However, if you wish to do it for ListSerializer, i.e for serializer = serializer_class(many=True), this won't work. You will get list of empty values. In that scenario, you could write your validations in def validate function and to avoid non_field_errors in your serialization error, you can raise ValidationError with error message as a dictionary instead of string.
def validate(self, data):
# do your validation
raise serializers.ValidationError({"your_field": "error_message"})
Solution 2:[2]
def validate(self, validated_data):
"""
validate and verifies the user data before getting saved.
:param validated_data: dict obj
:return: validated_data
"""
existing_data = self.to_representation(self.instance)
Solution 3:[3]
So if you're performing a create or update the plain unvalidated data can accessed in:
self.context['view'].get_serializer().data
Although the other solutions are in fact cleaner, we have a single model on a partitioned table and need another field that specifies the partition, since we're not partitioned on the primary key the database has no clue how to look it up.
EDIT: It appears that field is actually blank, you may have luck with the following, depending on how the Serializer is used (for this it must be used in a ViewSet)
self.context['view'].get_serializer().context['request'].data
Solution 4:[4]
One other simple solution is accessing the properties as below
class Keys_Serializer(serializers.Serializer):
key_id = serializers.IntegerField(required=True)
key_name = serializers.CharField(required=True)
value_id = serializers.IntegerField(required=False)
def validate_key_name(self, value):
#getting other field values as below
self.initialdata
#scrape data from initialdata
# incase of updation time use
# self.instance and self.inistialdata together to get respective ones
return value
Solution 5:[5]
I had a similar problem where I just needed other values for the output, not for validation but this could probably be a good starting point. It is based on https://www.django-rest-framework.org/api-guide/fields/#examples.
You need to override the get_attribute function to return the object instead of the attribute. From the docs:
class ClassNameField(serializers.Field):
def get_attribute(self, instance):
# We pass the object instance onto `to_representation`,
# not just the field attribute.
return instance
Then I was able to do stuff like
def to_representation(self, instance): # pylint: disable=arguments-renamed
return instance.my_function()
or
return f"{instance.attribute_1}, {instance.attribute_2}"
Solution 6:[6]
def validate_fieldname(self, value):
data = self.context['request'].data
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Vijay Anand Pandian |
| Solution 3 | |
| Solution 4 | DisappointedByUnaccountableMod |
| Solution 5 | Dakota |
| Solution 6 | rechie |
