Django rest framework Django Rest框架中的批量请求:作为序列化程序传递什么';s";“实例”;论点
我正在使用Django rest framework Django Rest框架中的批量请求:作为序列化程序传递什么';s";“实例”;论点,django-rest-framework,Django Rest Framework,我正在使用ListSerializer一次处理多个对象。它接受对象的JSON数组,即请求。数据是Python端dict的列表 在我的ListCreateAPIView中,我考虑重写get_object(),以便获取在补丁或放置请求中修改的对象。我计划通过在request.data列表中给出的对象上循环并从数据库中获取它们来实现这一点 (请注意,对于单个对象请求,通用工作流使用基于URL的查找字段来获取实例。但是,您无法在URL中标识多个对象。) 不幸的是,这种方法不能正确处理无效的请求。数据输入
ListSerializer
一次处理多个对象。它接受对象的JSON数组,即请求。数据是Python端dict
的列表
在我的ListCreateAPIView
中,我考虑重写get_object()
,以便获取在补丁
或放置
请求中修改的对象。我计划通过在request.data
列表中给出的对象上循环并从数据库中获取它们来实现这一点
(请注意,对于单个对象请求,通用工作流使用基于URL的查找字段来获取实例。但是,您无法在URL中标识多个对象。)
不幸的是,这种方法不能正确处理无效的请求。数据输入的情况,例如,当它不是列表时这是问题的根源。
那么,如何处理呢?以下是一些想法:
在get\u object()
view方法中执行额外的验证步骤
在调用serializer.save()
之前,不要在序列化程序中填充instance
,并修改save()
方法,以便获取现有实例并将其传递到update()
:
序列化程序的save()方法中的
instance=get_instances_(验证的_数据)#不基于request.data
如果self.instance不是None:
#在通用工作流中,这将传递预填充的self.instance
self.instance=self.update(实例,已验证的\u数据)
其他:
self.instance=self.create(已验证的_数据)
返回self.instance
在不传递实例的情况下初始化序列化程序,然后验证以确保负载是列表,然后获取实例,如下所示:
在视图的update()方法中
serializer=self.get\u序列化程序(无,数据=request.data,多个=True)
serializer.is\u有效(raise\u exception=True)
serializer.instance=self.get_object()#此行不同于一般工作流
self.perform\u更新(序列化程序)
考虑事项:
这种方法看起来很难看,因为用many=True
初始化的序列化程序的is\u valid()。此外,验证不是视图的任务。不幸的是,is\u valid()
仅在通用工作流中视图的get\u object()
方法之后调用,因此get\u object()
无法访问已验证的数据
这会将从视图的get\u object()
方法获取的实例移动到序列化程序。由于这也打破了DRF的概念结构,因此它也不是理想的解决方案
这似乎是最有希望的
但是,方法2.)和3.)还有另一个问题:序列化程序的数据
属性的返回值取决于self.instance
是否为None
。换句话说,通过稍后设置序列化程序的实例
属性,数据
属性的用户可能会获得不同的数据。(如果存在self.instance
,则data
对应于它,否则它对应于validated\u data
)
最好的方法是什么
额外问题:有时,验证取决于实例是被修改还是被创建。例如,如果实例有一个write once字段,其值在创建时提供,以后无法更改,则可能会发生这种情况。假设该字段不是主键,则只有在不存在实例的情况下,该字段才应被视为“必需”。这似乎是尽早将实例移交给序列化程序的一个很好的理由。但是,如果这样做需要访问请求。数据
,如果不先调用is valid()
就不能直接执行,您该怎么办?我最终得到了以下解决方案:
1.)在视图的get_object()
中返回过滤后的查询集:
###视图的get_object()方法:
def get_对象(自身):
返回self.filter\u queryset(self.get\u queryset())
根据DRF文件
2.)在视图中调用的序列化程序的构造函数将其保存到self.instance
,然后将其作为instance
参数传递给update()
方法。此方法也会传递验证的\u数据
。我们可以使用后者对前者进行一些过滤:
###序列化程序的update()方法:
def更新(自身、实例、已验证的_数据):
instance=instance.filter(…)#基于已验证的_数据
#继续你的逻辑
这是受以下观察结果启发的,即用户还循环使用验证的\u数据
,然后从实例
中选择项目,这可能是一个更大的集合,就像这里的查询集一样
使用这种方法,我们可以在序列化程序初始化时传递一些合理的内容作为实例,但在验证运行后对实例列表进行详细筛选
注意:有人可能认为将较大的查询集传递给序列化程序效率低下。但是,只有在使用update()
方法中过滤的实例
s时,才会计算queryset。换句话说,最终只会得到一个应用了所有筛选条件的数据库查询。我最终得到了以下解决方案:
1.)在视图的get_object()
中返回过滤后的查询集:
###视图的get_object()方法:
def get_对象(自身):
返回self.filter\u queryset(self.get\u queryset())
根据DRF文件
2.)视图中调用的序列化程序构造函数保存此