【问题标题】:django rest framework model serializers - read nested, write flatdjango rest 框架模型序列化器 - 读取嵌套,写入平面
【发布时间】: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

的许多相关字段时

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

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

【问题讨论】:

    标签: django django-rest-framework


    【解决方案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
    

    【讨论】:

    【解决方案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

    【讨论】:

      猜你喜欢
      • 2014-07-26
      • 2013-08-21
      • 2017-11-15
      • 2018-12-13
      • 2021-06-23
      • 2016-08-01
      • 2016-09-03
      • 2016-05-04
      • 1970-01-01
      相关资源
      最近更新 更多