[Answered ]-DRF serializer parsing comma-delimited string into a list field

1👍

The ListField will work with json, or with multi-value query strings or form bodies (as below). It does not parse comma separated strings.

This will work:
GET /path/?list_field=1&list_field=2&list_field=3

What you need is a custom field which implements your parsing logic: accept a string and split it using a separator (,, or :, etc), and then validate it using the child field.

There is no builtin field which works this way, but there is a great example GIST here which you can copy or reference when writing your own field. I have included some snippets from the gist, but as its not mine I don’t feel comfortable copying the whole thing.

# https://gist.github.com/imomaliev/77fdfd0ab5f1b324f4e496768534737e

class CharacterSeparatedField(serializers.ListField):
    def __init__(self, *args, **kwargs):
        self.separator = kwargs.pop("separator", ",")
        super().__init__(*args, **kwargs)

    def to_internal_value(self, data):
        data = data.split(self.separator)
        return super().to_internal_value(data)

    # continues ...

class TestCharacterSeparatedManyField:
    def test_field_from_native_should_return_list_for_given_str(self):
        field = CharacterSeparatedField(child=serializers.CharField())
        assert field.to_internal_value("a,b,c") == ["a", "b", "c"]

You can also write a custom validate_{fieldname} function to modify the value. This at least keeps it in the serializer. A proper Field is better if possible, though, but this is a common pattern for one-off validation/transformations like this.

class ExampleSerializer(Serializer):
    list_field = CharField()

    def validate_list_field(self, value):
        arr = value.split(",")
        arr = [int(x) for x in arr if x.isdigit()]
        if len(arr) == 0:
            raise ValidationError("Supply at least 1 value.")
        return arr
👤Andrew

Leave a comment