如何在通用视图中为同一请求使用不同的Django Rest Framework序列化程序

时间:2015-08-12 16:50:31

标签: django-rest-framework

我正在API项目中使用Django Rest Framework,并试图弄清楚是否有一种方法可以将两个不同的序列化程序与通用视图一起使用(例如CreateAPIView)。我想使用一个序列化程序来反序列化POST请求,而另一个序列化程序用于序列化生成的响应。

这是我正在努力做的事情;我将使用文档中的Album / Track示例进行说明:

我正在使用的模型具有ForeignKey关系。在API中,我希望能够在分配关系时在请求中包含FK,因此在序列化程序中我使用的是PrimaryKeyRelatedField,类似于AlbumSerializer处理与轨道的关系的方式:

class CreateAlbumSerializer(serializers.ModelSerializer):
    tracks = serializers.PrimaryKeyRelatedField(many=True)

    class Meta:
        model = Album
        fields = ('album_name', 'artist', 'tracks')

然而,在回复中,我想使用ModelSerializer包含相册的完整表示,而不仅仅是PK,slug等,如下所示:

class AlbumSerializer(serializers.ModelSerializer):
    tracks = TrackSerializer(many=True, read_only=True)

    class Meta:
        model = Album
        fields = ('album_name', 'artist', 'tracks')

class TrackSerializer(serializers.ModelSerializer):
    class Meta:
        model = Album
        fields = ('order', 'title', 'duration')

通用DRF视图允许您指定serializer_class或覆盖get_serializer_class方法,但我无法弄清楚如何使用它来完成我所追求的目标。

有什么明显的东西让我失踪吗?这似乎是一件合理的事情,但我似乎无法理解如何完成它。

1 个答案:

答案 0 :(得分:6)

方法#1

覆盖DRF ViewSet中的通用mixins。例如:

class MyViewSet(CreateModelMixin, MultipleSerializersViewMixin, ViewSet):
    serializer_class = CreateAlbumSerializer

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

        saved = self.perform_create(serializer)
        serializer = self.get_serializer(instance=saved, serializer_class=AlbumSerializer)

        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    def perform_create(self, serializer):
        return serializer.save()

MultipleSerializersViewMixin取自django-rest-framework-braces

方法#2

自定义to_representation的{​​{1}}。例如:

CreateAlbumSerializer

比较

我个人喜欢方法#1而不是#2,即使它更详细,因为它不会将任何自定义创建/响应逻辑泄漏给序列化程序。我认为序列化程序应该只知道如何序列化,并且应该在视图中完成为作业选择不同序列化程序的所有自定义要求。