Django 序列化程序 ManyToMany 重新运行名称数组而不是 ID 数组

Thu*_*orn 4 django django-rest-framework

我的模型:

class Category(models.Model):
    name = models.Charfield()..
    code = models.Charfield()...

class Movie(models.Model):
    name = models.Charfield()..
    categories = models.ManyToManyField(Category)
Run Code Online (Sandbox Code Playgroud)

我的序列化器

class MovieSerializer(serializers.ModelSerialier):
   class Meta:
      model= Movie
      fields = ['name',
               'categories',
      ]
Run Code Online (Sandbox Code Playgroud)

当我通过 id 获取电影时,它会返回:

[ {"name": "我的电影", "categories": [1, 2, 3], } ]

我希望我的回答是:....“类别”:[“乐趣”、“冒险”、...]

我尝试过的

class CategorySerializer(serializers.ModelSerializer):
   class Meta:
      model = Category
      fields = ['name']
  
   def to_representation(self, instance):
      return instance.name
Run Code Online (Sandbox Code Playgroud)

它给了我预期的结果,但我认为这不是一个干净的方法

Haf*_*uss 7

选项1

您可以使用您的模型__str__方法来实现此目的。只需使用StringRelatedField

class MovieSerializer(serializers.ModelSerialier):
   categories = serializers.StringRelatedField(many=True)
   class Meta:
      model= Movie
      fields = ['name', 'categories']
Run Code Online (Sandbox Code Playgroud)

并将该__str__方法添加到您的类别模型中:

class Category(models.Model):
    name = models.Charfield()
    code = models.Charfield()

    def __str__(self):
        return self.name
Run Code Online (Sandbox Code Playgroud)

选项2

使用自定义RelatedField,如文档中所述:

class CategoryListingField(serializers.RelatedField):
    def to_representation(self, value):
        return value.name

class MovieSerializer(serializers.ModelSerialier):
   categories = CategoryListingField(many=True)
   class Meta:
      model= Movie
      fields = ['name', 'categories']
Run Code Online (Sandbox Code Playgroud)

这与您所做的很接近,只是更干净一点,因为 aRelatedField正是为了实现这一目标而设计的。使用自定义序列化器不是这里的方法,因为您不想序列化对象本身,而只想序列化其中的特定字段。默认情况下,这是pk(或id),但通过指定您自己的相关字段,您可以将其更改为您想要的任何内容。