django rest 框架模型序列化器 - 读取嵌套,写入平面

Posted

技术标签:

【中文标题】django rest 框架模型序列化器 - 读取嵌套,写入平面【英文标题】:django rest framework model serializers - read nested, write flat 【发布时间】:2013-07-20 03:20:59 【问题描述】:

我的客户试图编写一个包含 fk 列表的表示


languages: [1]
last_name: "Beecher"
settings: 1
state: "NY"

但在阅读时,我希望有一个嵌套表示来减少往返次数


languages: [id:1, created:2013-07-21T01:38:33.569Z, modified:2013-07-21T01:38:33.569Z, language:testing]
last_name: "Beecher"
settings: 
created: "2013-07-20T22:04:17.998Z"
email_blog: false
email_booking_accepted_denied: false
email_booking_request: false
email_friend_joined: false
email_groups_added_network: false
email_new_review: false
email_news: false
email_upcoming_booking_remind: false
id: 1
mobile_booking_accepted_denied: false
mobile_booking_request: false
mobile_friend_joined: false
mobile_groups_added_network: false
mobile_new_review: false
mobile_upcoming_booking_remind: false
modified: "2013-07-20T22:04:18.000Z"
user: 1

state: "NY"

使用模型序列化程序和 depth=1 读取没有问题 - 但尝试写入会出现错误“ValueError('instance should be a queryset or other iterable with many=True')” 尝试检查 iter

的许多相关字段时

相反,关闭深度可以让写作如我所愿,但阅读就不好了。

这里有什么我完全想念的吗?看起来应该是一个简单的改变,但我只能让一个或另一个工作

【问题讨论】:

【参考方案1】:

感谢之前的帖子,为此我采用了基于 get_serializer_class 的类似解决方案。

我还希望能够根据方法更改序列化程序类。

首先,我向视图类添加了一个属性,其中包含将请求方法映射到序列化程序类的字典。

 serializer_classes = 
     'GET': NestedSerializer,
     'POST': FlatSerializer
 

然后,我定义了一个 mixin 以在我想要这种行为的地方使用。

class SwappableSerializerMixin(object):
    def get_serializer_class(self):
        try:
            return self.serializer_classes[self.request.method]
        except AttributeError:
            logger.debug('%(cls)s does not have the required serializer_classes'
                         'property' % 'cls': self.__class__.__name__)
            raise AttributeError
        except KeyError:
            logger.debug('request method %(method)s is not listed'
                         ' in %(cls)s serializer_classes' %
                         'cls': self.__class__.__name__,
                          'method': self.request.method)
            # required if you don't include all the methods (option, etc) in your serializer_class
            return super(SwappableSerializerMixin, self).get_serializer_class() es

【讨论】:

虽然这之前运行良好,但第一次失败,除了 DRF 3.6.3 上的文档功能 (django-rest-framework.org/topics/documenting-your-api)【参考方案2】:

我遇到了同样的问题,而且看起来很多其他人也有同样的问题。 Carlton Gibson 答案实际上将我引向了我的 hacky 解决方案。我最终使用了带有深度集的ModelSerializer,并创建了以下 mixin 以在视图中使用。

class ReadNestedWriteFlatMixin(object):
    """
    Mixin that sets the depth of the serializer to 0 (flat) for writing operations.
    For all other operations it keeps the depth specified in the serializer_class
    """
    def get_serializer_class(self, *args, **kwargs):
        serializer_class = super(ReadNestedWriteFlatMixin, self).get_serializer_class(*args, **kwargs)
        if self.request.method in ['PATCH', 'POST', 'PUT']:
            serializer_class.Meta.depth = 0
        return serializer_class

【讨论】:

在使用这种方法进行扩展时,您可能会遇到问题。 Meta 是一个类级别的变量,由所有实例共享。当您在尝试序列化一个对象时切换深度时,您会弄乱所有实例。【参考方案3】:

我想到的最简单的事情是在您的视图上覆盖get_serializer_class(),以便 POST/PUT 返回一个未指定深度参数的修改后的序列化程序,并为您的languages 字段使用PrimaryKeyRelatedField。

【讨论】:

以上是关于django rest 框架模型序列化器 - 读取嵌套,写入平面的主要内容,如果未能解决你的问题,请参考以下文章

python Django Rest_Framework框架 模型类序列化器(ModelSerializer)详解(图文并茂版)

python Django Rest_Framework框架 模型类序列化器(ModelSerializer)详解(图文并茂版)

Django rest框架 - 模型序列化程序不会序列化所有字段

django double left join + django rest 框架序列化器

如何从序列化器字段订购 django rest 框架查询集?

通过django rest框架序列化器添加外键数据