在单个视图中序列化多个模型 [英] Serialize multiple models in a single view

查看:169
本文介绍了在单个视图中序列化多个模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是这个场景:



我有两个模型; 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)
响应= files_serializer.data + dirs_serializer.data
返回响应(响应)

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



提前感谢

解决方案

您当前使用的代码,特别是链接无法正常工作的问题是因为您不是将任何上下文传递给序列化程序。

  class DirContents(generics.GenericAPIView):
def get(self,request,* args,** kwargs):
files = FileObj.objects.filter(parent = kwargs.get('dir_id'))
dirs = DirObj.objec ts.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

返回响应(响应)

自动完成使用mixin,但是对于这样的情况,需要手动传递。



对于任何人来说,将两个模型合并成一个序列化器:



在使用通用视图时,在一个视图中没有简单的方法支持多个不同的模型。看起来你似乎没有使用它们来过滤查询,所以这实际上是可以做的,虽然不是以某种方式被认为是干净的。



$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $
$ (parent = kwargs.get('dir_id'))
dirs = DirObj.objects.filter(parent = kwargs.get('dir_id'))

files_list =列表(文件)
dirs_list = list(dirs)

combined = files_list + dirs_list

serializer = YourCombinedSerializer(combined,many = True)

返回响应(serializer.data)


Here's the scenario:

I have two models; FileObj and DirObj.

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

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

And I have the following serializers:

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

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

And let's say that when a user browses to '/directories/[dir_id]' I want to return the file and directory content of the DirObj specified by 'dir_id' in a single view, that uses two different serializers. Right now I have (not exactly, but close enough so you get the gist) the following:

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)

This feels like an ugly hack. It also disregards any sort of hyperlinking that would be normally rendered when browsing the API (i.e., HyperlinkedRelatedFields do not appear as hyperlinks as they should.) Is there any way to serialize an arbitrary number of models and return them in a single view, without breaking the browsable API and/or having to do a (what I'm assuming to be) a bunch of extra work to get hyperlinking to work properly?

Thanks in advance!

解决方案

The issue you are facing with your current code, specifically with the links not working, is because you are not passing in any context to the serializer.

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)

This is done automatically for generic views that use the mixins, but for cases like this it needs to be passed in manually.

For anyone coming here to combine two models into a single serializer:

There is no easy way to support multiple different models in one view when using the generic views. It appears as though you are not using them for filtering querysets though, so this is actually possible to do, though not in a way that would be considered "clean" by any means.

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)

这篇关于在单个视图中序列化多个模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆