在单个视图中序列化多个模型

时间:2014-05-16 17:11:11

标签: python django django-rest-framework

以下是该方案:

我有两个型号; FileObj和DirObj。

class DirObj(models.Model):
    [...]
    parent = models.ForeignKey('self')
    [...]

class FileObj(models.Model):
    [...]
    parent = models.ForeignKey(DirObj)
    [...]

我有以下序列化器:

class FileObjSerializer(serializers.ModelSerializer):
    [...]
    class Meta:
        model = FileObj

class DirObjSerializer(serializers.HyperlinkedModelSerializer):
    [...]
    parent = serializers.HyperlinkedRelatedField(
        view_name = 'dirobj-detail')
    class Meta:
        model = DirObj

让我们说当用户浏览'/ directories / [dir_id]'时,我希望在单个视图中返回由'dir_id'指定的DirObj的文件目录内容,使用两个不同的序列化器。现在我有(不完全,但足够接近所以你得到的要点)以下内容:

class DirContents(generics.GenericAPIView):
    def get(self, request, *args, **kwargs):
        files = FileObj.objects.filter(parent = kwargs.get('dir_id'))
        dirs = DirObj.objects.filter(parent = kwargs.get('dir_id'))
        files_serializer = FileObjSerializer(files, many = True)
        dirs_serializer = DirObjSerializer(dirs, many = True)
        response = files_serializer.data + dirs_serializer.data
        return Response(response)

这感觉就像一个丑陋的黑客。它还忽略了在浏览API时通常会呈现的任何类型的超链接(即,HyperlinkedRelatedFields不像它们应该的那样显示为超链接。)有没有办法序列化任意数量的模型并在单个视图中返回它们,没有打破可浏览的API和/或不得不做一些额外的工作(我假设是什么)以获得超链接以正常工作?

提前致谢!

2 个答案:

答案 0 :(得分:6)

您当前代码所面临的问题,特别是链接不起作用,是因为您不是passing in any context序列化程序。

class DirContents(generics.GenericAPIView):
    def get(self, request, *args, **kwargs):
        files = FileObj.objects.filter(parent=kwargs.get('dir_id'))
        dirs = DirObj.objects.filter(parent=kwargs.get('dir_id'))

        context = {
            "request": request,
        }

        files_serializer = FileObjSerializer(files, many=True, context=context)
        dirs_serializer = DirObjSerializer(dirs, many=True, context=context)

        response = files_serializer.data + dirs_serializer.data

        return Response(response)

对于使用mixins的通用视图,这是自动完成的,但对于这种情况,需要手动传递。

对于任何来这里将两个模型组合到一个序列化程序中的人:

使用通用视图时,没有简单的方法可以在一个视图中支持多个不同的模型。看起来好像你没有使用它们来过滤查询集,所以这实际上是可行的,尽管不会被认为是" clean"无论如何。

class DirContents(generics.GenericAPIView):
    def get(self, request, *args, **kwargs):
        files = FileObj.objects.filter(parent=kwargs.get('dir_id'))
        dirs = DirObj.objects.filter(parent=kwargs.get('dir_id'))

        files_list = list(files)
        dirs_list = list(dirs)

        combined = files_list + dirs_list

        serializer = YourCombinedSerializer(combined, many=True)

        return Response(serializer.data)

答案 1 :(得分:0)

使用选项DirObjSerializer将文件添加到many=True作为相关字段。 有关详细信息:http://www.django-rest-framework.org/api-guide/relations

class DirObj(models.Model):
    [...]
    parent = models.ForeignKey('self')
    [...]

 class FileObj(models.Model):
    [...]
    parent = models.ForeignKey(DirObj, related_name='files')
    [...]


class FileObjSerializer(serializers.ModelSerializer):
    [...]
    class Meta:
        model = FileObj

class DirObjSerializer(serializers.HyperlinkedModelSerializer):
    [...]
    parent = serializers.HyperlinkedRelatedField(
        view_name = 'dirobj-detail')
    files = serializers.HyperlinkedRelatedField(many=True,
        view_name = 'fileobj-detail')

    class Meta:
        model = DirObj