Reputation: 1835
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:
ListField
is possible with no problem? Or, can I pass min_length
and max_length
arguments with many=True
?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
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:
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.
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.obj_list[0].vlist
is a List of OrderedDict objects, not a List of Hourly
objects.Upvotes: 3