J. Choi
J. Choi

Reputation: 1835

Django REST Framework serializer for a list of dictionaries

I'm new to Django REST Framework and searching for a method to serialize a list of dictionaries.

Target data is a time-series. Each dictionary contains hourly value and each list contains hourly values of a day.

class Hourly:
   hour = None
   value = None

   def __init__(self, hour, value):
      self.hour = hour
      self.value = value


class Daily:
   date = None
   vlist = None

   def __init__(self, date, vlist):
      self.date = date
      self.vlist = vlist

It is easy to create a serializer for the hourly class by following the Django REST Framework API guide.

class HourlySerializer(serializers.Serializer):

    hour = serializers.IntegerField(required=True, min_value=0, max_value=23)
    value = serializers.FloatField(required=True)

    def create(self, validated_data):
        return Hourly(**validated_data)

    def update(self, instance, validated_data):
        instance.hour = validated_data.get('hour', instance.hour)
        instance.value = validated_data.get('value', instance.value)
        return instance

My objective is simple: creating a serializer for the daily data. (1) The serializer must restrict the length of data as 24. (2) It should have an ability to validate each hourly data.


#1. Using ListField

In case of restricting the data length, ListField has arguments min_length and max_length #.

I think this kind of code may be possible #, however, the API guide does not say anything about defining the child of a ListField as a serializer.

class DailySerializer(serializers.Serializer):
    date = serializers.DateField(required=True)
    vlist = serializers.ListField(child=HourlySerializer(), min_length=24, max_length=24)


#2. Using ListSerializer

The API guide says one can nest serializers just like they are fields. If the nested value is a list of items, many=True can be used to initiate ListSerializer. However, there is no argument about restricting the data length.

class DailySerializer(serializers.Serializer):
    date = serializers.DateField(required=True)
    vlist = HourlySerializer(many=True)


Here are my questions:

  1. Is the method using ListField is possible with no problem? Or, can I pass min_length and max_length arguments with many=True?
  2. The API guide does not say anything about defining create() and update() for ListField or ListSerializer. There are only cases for a nested serializer without many option # and a ListSerializer without non-list field #. Is there any example about this?

Upvotes: 5

Views: 10515

Answers (1)

J. Choi
J. Choi

Reputation: 1835

Answer to my own question.

class DailySerializer(serializers.Serializer):
   date = serializers.DateField(required=True)
   vlist = serializers.ListField(child=HourlySerializer(), min_length=24, max_length=24)

   def create(self, validated_data):
      return Daily(**validated_data)

   def update(self, instance, validated_data):
      instance.date = validated_data.get('date', instance.date)
      instance.vlist = validated_data.get('vlist', instance.vlist)
      return instance

Above ListField based DailySerializer is tested with the below input.

[
{'date': '2000-01-01', 'vlist': [{'hour':'00', 'value': '012'}, {'hour':'01', 'value': '123'}, ...],
{'date': '2000-01-02', 'vlist': [{'hour':'00', 'value': '012'}, {'hour':'01', 'value': '123'}, ...],
...,
]

To deal with the additional multi-day nest, serializer in the view is defined with many=True.

serializer = DailySerializer(data=data, many=True)

Test results are below:

  1. Using the ListField method does not make any problem during validation.
    Changing some hourly value as an arbitrary string is detected as an non-integer value.
    Daily data with its length not equal to 24 is also detected.

  2. Using naive create() and update() methods with ListField can be problematic.

  • obj_list = serializer.validated_data returns a List of OrderedDict objects.
  • obj_list = serializer.save() returns a List of Daily objects.
    However, obj_list[0].vlist is a List of OrderedDict objects, not a List of Hourly objects.

Upvotes: 3

Related Questions