25

I am having struggle with understanding ListField and DictField. I want to use it as a field on a serializer. I have a ListField which probably will contain many DictField. I tried to write a serializer as below:

class StopOncomingSerialier(serializers.Serializer):
    idn = serializers.IntegerField(read_only=True)
    buses = serializers.ListField(
        child=serializers.DictField(
            idn=serializers.IntegerField(read_only=True),
            stops_left=serializers.IntegerField(read_only=True)
        ),
    read_only=True
    )

I know, it does not make sense, since the documentation says DictField and ListField take child as argument. And so, the code above naturally raised error:

TypeError: __init__() got an unexpected keyword argument 'stops_left'

Desired Output

{
    "idn": 1,
    "buses": [
        {"idn": 11, "stops_left": 4},
        {"idn": 12, "stops_left": 15}
    ]
}

How to achieve this? buses is a list and might contain as many elements as I want.


Environment

  • python 3.5.1
  • django 1.9.6
  • django-rest-framework 3.3.3
Eray Erdin
  • 2,633
  • 1
  • 32
  • 66
  • 1
    Shouldn't `child` be a serializer class rather than a field instance? **[edit: no it shouldn't, my bad]** – spectras Jun 04 '16 at 11:26
  • [Documentation example](http://www.django-rest-framework.org/api-guide/fields/#listfield) puts `Field` instead of `Serializer`, that is why I did that, but I am going to try with `Serializer` to know if it works. – Eray Erdin Jun 04 '16 at 11:28

1 Answers1

35

I think instead of doing that, you should use nested serializers.

Create a BusSerializer having fields idn and stops_left. Then include this serializer in your StopOncomingSerializer as buses field with many=True argument to handle multiple buses data.

class BusSerializer(serializers.Serializer):
    idn = serializers.IntegerField(read_only=True)
    stops_left = serializers.IntegerField(read_only=True)


class StopOncomingSerialier(serializers.Serializer):
    idn = serializers.IntegerField(read_only=True)
    buses = BusSerializer(many=True)
Rahul Gupta
  • 46,769
  • 10
  • 112
  • 126
  • Could you give the example how to post data using `StopOncomingSerialier` ?. I have tried your solution and I got empty list if I get the data from `.validated_data` but I can get raw json if I get the data from `request.data` – Adiyat Mubarak Aug 16 '16 at 11:48
  • For sample data, please check this [SO link](http://stackoverflow.com/questions/37630032/adding-many-serializer-to-a-nested-serializer-field) which is related to this question. Also, did you call the `.is_valid()` method on the serializer to access the `validated_data`? – Rahul Gupta Aug 16 '16 at 17:27
  • @RahulGupta And what the model should look like then, if you don't mind me asking? I'm currently using MongoDB and would like to write a json Document (not plain text) into my database. Is it possible? – Albert Apr 29 '18 at 13:01
  • @Albert For mongodb, you need to use [DRF-Mongoengine](https://github.com/umutbozkurt/django-rest-framework-mongoengine). Also, it would be helpful if you post another question with the corresponding models. – Rahul Gupta Apr 30 '18 at 05:09
  • @RahulGupta I did yesterday, here's my question https://stackoverflow.com/questions/50091847/how-to-deal-with-deeply-nested-jsons-in-django-being-used-together-with-djongo-f I made an edit there. Would you please take a look? – Albert Apr 30 '18 at 08:18
  • Nested structure supports only ModelSerializer, as it implemented it with a function called build_nested_field. And restrictions were set in ModelSerializer.get_fields funtion. – Sphynx-HenryAY Jan 15 '19 at 04:14