Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django rest framework Django Rest框架中的批量请求:作为序列化程序传递什么';s";“实例”;论点_Django Rest Framework - Fatal编程技术网

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.)视图中调用的序列化程序构造函数保存此