不要在 DRF 序列化中使用字段名称只有一个字段

问题描述

我希望嵌套模型的序列化不包括每个实例的字段名称,因为序列化中只有一个字段。

我在 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 是 ManyToManyField,因为一个人可以说多种语言,而一种语言可以被多人使用。

我在 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']

目前序列化为 JSON 看起来像这样:

{"name": "Elizabeth II","languages": [{"code":"en"},{"code":"fr"}]}

但我希望它看起来像这样:

{"name": "Elizabeth II","languages": ["en","fr"]}

而且这应该不会有问题,因为在语言序列化中只有一个字段,永远不会有另一个字段,所以"code"字段名称是多余的。

如何实现?

更新:当通过 DRF 从 JSON 创建一个新人时,如何使它也能工作?

我在 views.py 中有以下视图:

class CreatePersonView(generics.CreateAPIView):
    queryset = Person.objects.all()
    serializer_class = PersonSerializer

解决方法

您可以像这样更改序列化程序。

class PersonSerializer(serializers.ModelSerializer):
    languages = serializers.SerializerMethodField()

    class Meta:
        model = Person
        fields = ['name','languages']

     def get_languages(self,obj):
        return obj.languages.all().values_list('name')
,

这就是我实现想要的行为的方式:

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']