Reputation: 4060
How do I write a serializer that validates a list of dictionaries?
Sample payload being sent is:
"payment_discount": [
{
"discount_rule_id": 1,
"discount_rule_name": "10 day early payment",
"discount_earned": "298.00"
},
{
"discount_rule_id": 2,
"discount_rule_name": "Store discount",
"discount_earned": "5.50"
},
]
Taking from this SO answer and this:
class PaymentDiscountSerializer(serializers.DictField):
discount_rule_id = serializers.IntegerField(required=False)
discount_rule_name = serializers.CharField(max_length=50)
discount_earned = serializers.DecimalField(max_digits=10, decimal_places=3)
class PaymentDiscountListSerializer(serializers.ListField):
"""Serialize discount object"""
child = PaymentDiscountSerializer()
class PaymentSerializer(serializers.ModelSerializer):
payment_discount = PaymentDiscountListSerializer()
# Other model fields
With this, I can get access to the payment_discount object in the payload using serializer.data but unfortunately no validations are being done against the dictionary if e.g. the payload includes discount_earned value of that is not of type Decimal
using: Django==1.10.2 & djangorestframework==3.5.1
Upvotes: 3
Views: 7505
Reputation: 648
I think you can simplify your serializers... Haven't tested it but you could use something like this:
class PaymentDiscountSerializer(serializers.Serializer):
"""Serialize discounts"""
discount_rule_id = serializers.IntegerField(required=False)
discount_rule_name = serializers.CharField(max_length=50)
discount_earned = serializers.DecimalField(max_digits=10, decimal_places=3)
class PaymentSerializer(serializers.ModelSerializer):
payment_discount = PaymentDiscountSerializer(many=True)
# Other model fields
It should give you a list of object like you want.
For the validation, it should work right out of the box like this.
But again, I haven't tested it. If you are having problems with your validations, you can define your own. Example:
class PaymentDiscountSerializer(serializers.Serializer):
"""Serialize discounts"""
discount_rule_id = serializers.IntegerField(required=False)
discount_rule_name = serializers.CharField(max_length=50)
discount_earned = serializers.DecimalField(max_digits=10, decimal_places=3)
def validate_discount_rule_id(self, value):
# Validation logic of the discount_rule_id field
#
return value
def validate(self, attrs):
# Validation logic of all the fields
#
return attrs
see http://www.django-rest-framework.org/api-guide/serializers/#field-level-validation for more infos.
Upvotes: 10