首页 > 解决方案 > Django Rest Framework:如何自定义 serializer.data 的值?

问题描述

当我调用时serializer.data,ManyToManyField 将显示为 id 列表,

但我希望它显示tags名称而不是 id。

模型.py

class Tag(models.Model):
    name = models.CharField(unique=True, max_length=20)


class Story(models.Model):
    title = models.CharField(max_length=100)
    tags = models.ManyToManyField(Tag)

序列化程序.py

from rest_framework import serializers

from stories.models import Story, Tag


class TagSerializer(serializers.ModelSerializer):
    class Meta:
        model = Tag
        fields = ('name',)


class StorySerializer(serializers.ModelSerializer):
    class Meta:
        model = Story
        fields = ('title', 'tags')

    def is_valid(self, raise_exception=False):
        self.initial_data['tags'] = self.get_tags_ids(self.initial_data['tags'])
        return super().is_valid(raise_exception)

    def get_tags_ids(self, tags):
        tags_ids = []
        for tag in tags:
            tag, _ = Tag.objects.get_or_create(name=tag)
            tags_ids.append(tag.id)

        return tags_ids

然后在外壳中

In [1]: from stories.serializers import StorySerializer                         

In [2]: StorySerializer()                                                       
Out[2]: 
StorySerializer():
    title = CharField(max_length=100)
    tags = PrimaryKeyRelatedField(allow_empty=False, many=True, queryset=Tag.objects.all())

In [3]: TEST_DATA = { 
...:     'title': 'A story', 
...:     'tags': ['horror', 'action'], 
...: }                                                                       

In [4]: ser = StorySerializer(data=TEST_DATA)                                     

In [5]: ser.is_valid()                                                            
Out[5]: True

In [6]: ser.data                                                                  
Out[6]: {'title': 'A story', 'tags': [1, 2]}

如何让ser.data返回{'title': 'A story', 'tags': ['horror', 'action']}

标签: djangodjango-rest-framework

解决方案


您可以使用StringRelatedField 链接

在你的模型中添加这个method

class Tag(models.Model):
    name = models.CharField(unique=True, max_length=20)

    def __str__(self) :  # <- This Method in Tag Model
        return self.name

序列化程序.py

class StorySerializer(serializers.ModelSerializer):
    tags = serializers.StringRelatedField(many=True) # <- This line
    class Meta:
        model = Story
        fields = ('title', 'tags')

还有另一种方法 -嵌套序列化器

序列化程序.py

class TagsSerializer(serializers.ModelSerializer): # <- This Serializer
    class Meta:
        model = Tags
        fields = ('name',)

class StorySerializer(serializers.ModelSerializer):
    tags = TagsSerializer(many=True, read_only=True) # <- This line
    class Meta:
        model = Story
        fields = ('title', 'tags')

推荐阅读