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

mus*_*XXX 1 python django django-rest-framework

这是场景:

我有两个型号; FileObj和DirObj.

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

class FileObj(models.Model):
    [...]
    parent = models.ForeignKey(DirObj)
    [...]
Run Code Online (Sandbox Code Playgroud)

我有以下序列化器:

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

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

让我们说当用户浏览'/ 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)
Run Code Online (Sandbox Code Playgroud)

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

提前致谢!

Kev*_*own 6

您当前的代码所面临的问题,特别是链接不起作用,是因为您没有将任何上下文传递给序列化程序.

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)
Run Code Online (Sandbox Code Playgroud)

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

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

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

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)
Run Code Online (Sandbox Code Playgroud)