Reputation: 18735
Is there a way to group fields in Serializer/ModelSerializer or to modify JSON structure?
There is a Location
model:
class Location(Model):
name_en = ...
name_fr = ...
...
If I use ModelSerializer
I get plain representation of the object fields like:
{'name_en':'England','name_fr':'Angleterre'}
I want to group some fields under "names" key so I get
{'names':{'name_en':'England','name_fr':'Angleterre'}}
I know I can create custom fields but I want to know if there is a more straightforward way. I tried
Meta.fields = {'names':['name_en','name_fr']...}
which doesn't work
Upvotes: 1
Views: 971
Reputation: 1868
You could also not use a property on the model and but use a SerializerMethodField
on your serializer like in this implementation.
We used here a _meta.fields
, like in the other implementation, to get all the fields that starts with name_
so we can dynamically get the output you desired
class LocationSerializer(serializers.ModelSerializer):
names = serializers.SerializerMethodField()
def get_names(self, obj):
lst = {field.name: getattr(obj, field.name)
for field in obj.__class__._meta.fields
if field.name.startswith('name_')}
return lst
class Meta:
model = Location
fields = ('id', 'names')
Upvotes: 0
Reputation: 1868
I think it is better using a property. Here is the whole example.
class Location(models.Model):
name_en = models.CharField(max_length=50)
name_fr = models.CharField(max_length=50)
@property
def names(self):
lst = {field.name: getattr(self, field.name)
for field in self.__class__._meta.fields
if field.name.startswith('name_')}
return lst
In views
:
class LocationViewSet(viewsets.ModelViewSet):
model = models.Location
serializer_class = serializers.LocationSerializer
queryset = models.Location.objects.all()
And in serializers
:
class LocationSerializer(serializers.ModelSerializer):
class Meta:
model = Location
fields = ('id', 'names')
My result for my fake data:
[{
"id": 1,
"names": {
"name_en": "England",
"name_fr": "Angleterre"}
}]
Upvotes: 4
Reputation: 998
Try to create a wrapper serialzer and place the LocationSerializer inside it
class LocationSerialzer(serializers.ModelSerialzer):
name_en = ...
name_fr = ...
...
class MySerializer(serializers.ModelSerializer):
name = LocationSerialzer()
...
Using the above method , you can apply your own customization without being limited to drf custom fields.
Upvotes: 1