Is it possible to dynamically change field name in django-rest-framework serializer?
I have models Product
and ProductCategory
.
Let's say I have a ProductCategory TV
that has
Sony
, Samsung
as its products. I also have a category MobilePhone
with Apple
and Nokia
as my products. Using DRF, I would like to receive JSON output using serializers that is similar to the one below:
{
'TV':
[
'Sony':
{
'price': '$100',
'country': 'Japan',
},
'Samsung':
{
'price': '$110',
'country': 'Korea',
}
]
'mobile_phone':
[
'Apple':
{
'price': '$300',
'country': 'USA',
},
'Nokia':
{
'price': '$210',
'country': 'Finland',
}
]
}
The problem here is that the field names ('TV', 'mobile_phone')
in the serializer must be dynamic.
I know I can get the following JSON type
{
[
{
'product_category': 'TV',
'manufacturer: 'Sony',
'price': '$100',
'country': 'Japan',
},
{
'product_category': 'TV',
'manufacturer: 'Samgsung',
'price': '$110',
'country': 'Korea',
}
]
[
{
'product_category': 'mobile_phone',
'manufacturer: 'Samgsung',
'price': '$300',
'country': 'USA',
},
{
'product_category': 'mobile_phone',
'manufacturer: 'Apple',
'price': '$210',
'country': 'Finland',
}
]
}
from
class CategorySerializer(serializers.Serializer):
product_category = serializer.CharField()
manufacturer = serializer.CharField()
price = serializer.CharField()
country = serializer.CharField()
But the names of dynamically changing fields are difficult to achieve. Is there a way to do this?
source to share
You can support this kind of custom format by overriding to_representation
your Serializer and the default ListSerializer :
-
First, you override
to_representation
your serializer:class CategorySerializer(serializers.Serializer): # your fields here def to_representation(self, obj): return { obj.manufacturer: { 'price': obj.price, 'country': obj.country } }
So, your serialized categories are of the following form:
{ 'Sony': { 'price': '$100', 'country': 'Japan' } }
-
Then, to add
product_category
before your list, you can use your own ListSerializer with a custom oneto_representation
:class CategoryListSerializer(serializers.ListSerializer): def to_representation(self, data): # Group your data entries by category here ... return { 'TV': tv_data 'mobile_phone': mobile_data } class CategorySerializer(serializers.Serializer): ... class Meta: list_serializer_class = CategoryListSerializer
source to share