Django REST框架更新嵌套的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

任何人都可以建议更好的解决方案吗?

P.S。在这种情况下可以创建或更新操作,因此我不能仅在序列化器上使用many=True,因为它也需要instance进行更新。

如果您在保存上触发了很长的列表或操作,则在此处使用for for loop with Repains将是一个杀手。我会尽力避免使用它。您最好使用orms更新with where子句:https://docs.djangoproject.com/en/en/2.0/topics/db/queries/#updating-multiple-objects-at-yce,甚至从写入后的数据库

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

也有一个:https://github.com/aykut/django-bulk-update(免责声明:我不是包裹的贡献者或作者(。

您必须意识到此方法的缺点 - 如果您使用任何帖子/pre_保存信号,则这些信号不会被更新触发。

通常,运行多个保存会杀死数据库,您可能最终很难诊断僵局。在一个项目中,我从循环中的save((转移到更新((的一个项目中,将响应时间从30秒的时间减少到<10最长的操作留在发送电子邮件的地方。

相关内容

最新更新