Django Rest Framework更新嵌套的m2m对象。有谁知道更好的方法?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django Rest Framework更新嵌套的m2m对象。有谁知道更好的方法?相关的知识,希望对你有一定的参考价值。

我有一个案例,用户需要更新一个instance以及在此实例上添加/编辑m2m相关对象。

这是我的解决方案:

# models.py

class AdditionalAction(SoftDeletionModel):
    ADDITIONAL_CHOICES = (
        ('to_bring', 'To bring'),
        ('to_prepare', 'To prepare'),
    )
    title = models.CharField(max_length=50)
    type = models.CharField(choices=ADDITIONAL_CHOICES, max_length=30)

class Event(models.Model):
     title= models.CharField(max_length=255)
     actions = models.ManyToManyField(AdditionalAction, blank=True)



# serializers.py
class MySerializer(serializers.ModelSerializer):
    def update(self, instance, validated_data):
        actions_data = validated_data.pop('actions')

        # Use atomic block to rollback if anything raised Exception 
        with transaction.atomic():

            # update main object
            updated_instance = super().update(instance, validated_data)

            actions = []
            # Loop over m2m relation data and
            # create/update each action instance based on id present
            for action_data in actions_data:
                action_kwargs = {
                    'data': action_data
                }
                id = action_data.get('id', False)
                if id:
                    action_kwargs['instance'] = AdditionalAction.objects.get(id=id)
                actions_ser = ActionSerializerWrite(**action_kwargs)
                actions_ser.is_valid(raise_exception=True)
                actions.append(actions_ser.save())

            updated_instance.actions.set(actions)

        return updated_instance

谁能建议更好的解决方案?

附:在这种情况下可以创建或更新动作,所以我不能在序列化器上使用many=True,因为它还需要instance来更新。

答案

如果你有一个很长的列表或在保存时触发的动作,那么在这里使用for循环将是一个杀手。我会尽量避免它。最好使用ORMS更新和where子句:https://docs.djangoproject.com/en/2.0/topics/db/queries/#updating-multiple-objects-at-once,甚至在写入后从数据库中读取更新的对象。

要创建新操作,您可以使用bulk_create:https://docs.djangoproject.com/en/2.0/ref/models/querysets/#bulk-create

还有这一个:https://github.com/aykut/django-bulk-update(免责声明:我不是该包的撰稿人或作者)。

您必须了解此方法的缺点 - 如果您使用任何post / pre_ save信号,那么更新不会触发这些信号。

通常,运行多次保存会终止数据库,最终可能难以诊断死锁。在其中一个项目中,我致力于从循环中的save()转换到update(),将响应时间从30秒减少到<10,其中最长的操作离开发送电子邮件的地方。

以上是关于Django Rest Framework更新嵌套的m2m对象。有谁知道更好的方法?的主要内容,如果未能解决你的问题,请参考以下文章

在 Django Rest Framework 中正确更新嵌套序列化程序

Django Rest Framework,如何更新序列化程序中的嵌套值

Django Rest Framework更新嵌套的m2m对象。有谁知道更好的方法?

django-rest-framework、多表模型继承、ModelSerializers 和嵌套序列化器

需要 Django Rest Framework 嵌套序列化程序 = False 错误

Django REST Framework:嵌套序列化程序未出现