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 框架序列化器