首页 > 解决方案 > 在序列化程序中更改创建时的返回类型

问题描述

我有以下两个序列化程序:

class ProgramSerializer(serializers.ModelSerializer):
    class Meta:
        from radio.models import Program
        model = Program
        fields = ('id', 'title')

class UserRecentlyPlayedSerializer(serializers.ModelSerializer):
    program_data = ProgramSerializer(read_only=True)
    class Meta:
        model = UserRecentlyPlayed
        fields = ('id', 'user', 'program', 'program_data',)

它们基于以下模型:

class Program(models.Model):
    title = models.CharField(max_length=64)

class UserRecentlyPlayed(models.Model):
    user = models.ForeignKey(User)
    program = models.ForeignKey(Program)

我要做的是:在创建时,我希望能够以以下方式创建 UserRecentlyPlayed 的新实例:

{
    "user": "...user id ....",
    "program": "....program id...."
}

但是,当我返回一个列表时,我想返回以下内容:

[{
     "id": "... id .... ",
     "user": ".... user id .....",
     "program": {"id": "...program id...", "title": "...title..." }
 }]

这些在以下视图中被调用:

class RecentlyPlayed(generics.ListCreateAPIView):
    serializer_class = UserRecentlyPlayedSerializer

不幸的是,这不起作用。什么是正确的魔法?

标签: djangodjango-rest-framework

解决方案


您可以将您program_data的序列化程序重命名为program,也可以为嵌套序列化程序指定源。

那应该根据您的需要返回 list 的输出。

class UserRecentlyPlayedSerializer(serializers.ModelSerializer):
    program = ProgramSerializer(read_only=True)
    class Meta:
        model = UserRecentlyPlayed
        fields = ('id', 'user', 'program',)

或者

class UserRecentlyPlayedSerializer(serializers.ModelSerializer):
    program_data = ProgramSerializer(read_only=True, source='program')
    class Meta:
        model = UserRecentlyPlayed
        fields = ('id', 'user', 'program_data',)

为了支持创建相同的 json 输入,最简单的方法是为输入创建另一个序列化程序:

class UserRecentlyPlayedSerializerInput(serializers.ModelSerializer):
    program = serializers.PrimaryKeyRelatedField(queryset=Program.objects.all())

    class Meta:
        model = UserRecentlyPlayed
        fields = ('id', 'user', 'program',)

当请求为 POST/PUT/PATCH 时,在您的视图中使用它:

class RecentlyPlayed(generics.ListCreateAPIView):
    serializer_class = UserRecentlyPlayedSerializer    

    def get_serializer_class(self):
        if self.request.method.lower() == 'get':
            return self.serializer_class

        return UserRecentlyPlayedSerializerInput

虽然这对于“获取”很有用,但我希望在创建后看到相同的结果。我仍然看到 {"program": "...id...."

为此,您必须在视图中稍微更改 create 方法的实现

   def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        instance = serializer.save()
        headers = self.get_success_headers(serializer.data)

        oser = UserRecentlyPlayedSerializer(instance)

        return Response(oser.data, status=status.HTTP_201_CREATED, 
headers=headers)

推荐阅读