DRF - Array of integers

Viewed 2666

I need to post an array of integers to a DRF serializer.

The serializer is:

class ItemSerializer(serializers.Serializer):
    id = serializers.IntegerField(required = False)
    selected_items = serializers.ListField(child = serializers.IntegerField())

From the FE I simply post via typescript an array:

createItem () {
    let tmp: any = {};
    const itemData = new FormData();
    itemData.append('id',1);
    itemData.append('selected_items', this.current.selected_items.map( e => e.id))

    return this.itemService.createItem( itemData )
        .subscribe( data => this.goBack( data ),
            err => {
                console.log( err );
                this.toastr.error( 'Item not saved', 'Error' )
            } );
}

itemService.createItem only does a http.post

When FE sends data to BE the selected_items field is encoded as selected_items=1,2 (verified via wireshark). When data is parsed from DRF the field is encoded as selected_items=['1,2']. So the field is not validated because 1,2 is not a valid integer.

1 Answers

If you are getting comma separated values in request, then you might want to convert it to an actual list before it goes for the validation.

just override the to_internal_value() method in your serializer to convert values.

class ItemSerializer(serializers.Serializer):
    id = serializers.IntegerField(required = False)
    selected_items = serializers.ListField(child = serializers.IntegerField())

    def to_internal_value(self, data):
        """
        method is called to restore a primitive datatype into its internal python representation. This method should raise a serializers.ValidationError if the data is invalid. 
        reference: https://www.django-rest-framework.org/api-guide/fields/#custom-fields
        """
        # Convert comma separated digits to list of integers
        data['selected_items'] = data['selected_items'].split(',') if data['selected_items'] else []
        return data

or else, you can write a custom field-level validation:

class ItemSerializer(serializers.Serializer):
    id = serializers.IntegerField(required = False)
    selected_items = serializers.ListField(child = serializers.IntegerField())

    def validate_selected_items(self, value):
        """
        You can specify custom field-level validation by adding .validate_<field_name> methods to your Serializer subclass.
        reference: https://www.django-rest-framework.org/api-guide/serializers/#field-level-validation
        """
        # Convert comma separated digits to list of integers
        return value.split(',') if value else []
Related