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

8 浏览
0 Comments

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

这是一个场景:

我有两个模型: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)

这感觉像是一个丑陋的hack。它也忽略了在浏览API时通常渲染的任何超链接(即,HyperlinkedRelatedFields不会显示为超链接,而是应该显示为超链接)。有没有一种方法可以序列化任意数量的模型并在一个单一的视图中返回它们,而不会破坏可浏览的API和/或不必做额外的工作来使超链接正常工作?

提前致谢!

0
0 Comments

在这个问题中,出现的原因是需要在单个视图中序列化多个模型,并将它们作为分开的实体返回,而不是嵌套在一起。解决方法是在DirObjSerializer中添加文件(FileObj)作为相关字段,并使用many=True选项。

为了实现这个解决方法,需要在DirObjSerializer中添加一个文件(FileObj)字段,该字段使用many=True选项。以下是实现的代码:

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

这样做可以将FileObjs作为单独的实体返回,而不是嵌套在DirObj中。此外,需要确保DirObj模型中的parent字段与FileObj模型中的'fileobj'相关字段匹配。

通过这种方法,可以在单个视图中序列化多个模型,并将它们作为分开的实体返回,而不是嵌套在一起。

0
0 Comments

在当前的代码中,遇到的问题是链接无法正常工作,这是因为没有向序列化器中传递任何上下文的原因。

这个问题可以通过手动传递上下文来解决。对于使用混合类的通用视图,这是自动完成的。但是对于像这样的情况,需要手动传递上下文。

如果要在一个视图中支持多个不同的模型,使用通用视图是没有简单的方法的。但是,如果不使用它们来过滤查询集,实际上可以这样做,尽管这种方法不会被认为是“干净”的。

通过在序列化器中传递上下文确实修复了超链接的问题。我将继续寻找一种干净的方法来序列化模型,但是你的答案基本上回答了我的问题(并给了我更多的阅读材料)。谢谢!

这个解决方案给了我一个很好的思路,谢谢。

0