I want the serialization of a nested model not to include the field name for every instance, since there is only one field in the serialization.
I have the following models in models.py
:
class Language(models.Model):
name = models.CharField(max_length=32)
code = models.CharField(max_length=32, unique=True)
class Person(models.Model):
name = models.CharField(max_lenght=128)
languages = models.ManyToManyField(Language, blank=True) # the languages this person speaks
languages is a ManyToManyField
since one person can speak many languages and one language can be spoken by many people.
I have for them the following serializers in serializers.py
:
class LanguageSerializer(serializers.ModelSerializer):
class Meta:
model = Language
fields = ['code']
class PersonSerializer(serializers.ModelSerializer):
languages = LanguageSerializer(many=True, required=False)
class Meta:
model = Person
fields = ['name', 'languages']
Currently the serialization into a JSON looks like something like this:
{"name": "Elizabeth II", "languages": [{"code":"en"}, {"code":"fr"}]}
but I would like it to look like this:
{"name": "Elizabeth II", "languages": ["en", "fr"]}
And this will should not cause a problem, because there is only one field in the serialization of language and there will never be another field, so the "code"
field name is redundant.
How can this be achieved?
Update: How can this be made to also work when creating a new person from a JSON over DRF?
I have the following view in views.py
:
class CreatePersonView(generics.CreateAPIView):
queryset = Person.objects.all()
serializer_class = PersonSerializer
This is how I achieved the wanted behaviour:
serializers.py
:
class LanguageRelatedField(serializers.StringRelatedField):
def get_queryset(self):
return Language.objects.all()
def to_representation(self, instance):
return instance.code
def to_internal_value(self, data):
try:
return Language.objects.get(code=data)
except Language.DoesNotExist:
raise serializers.ValidationError('Language {} could not be recognized'.format(data))
class PersonSerializer(serializers.ModelSerializer):
languages = LanguageRelatedField(many=True, required=False)
class Meta:
model = Person
fields = ['name', 'languages']