在 Django DRF 中一起更新多个资源

Update multiple resource together in Django DRF

假设我在 Django 中有两个模型:

class Inventory(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    added_by = models.ForeignKey(User, on_delete=models.SET("anonymous"),
                                 blank=True, null=True)
    name = models.CharField(max_length=100, unique=True)
    nickname = models.CharField(max_length=100, blank=True, null=True)
class InventoryProperties(models.Model):
    key = models.CharField(max_length=100)
    value = models.CharField(max_length=100)
    order = models.IntegerField()
    item = models.ForeignKey(Inventory, on_delete=models.CASCADE, related_name='properties')

如果我想在同一页面(表单)的前端向它添加库存和一些属性怎么办。

那么我必须先保存库存项目,然后再保存属性。

正如我在 REST 中读到的那样,这不应该用一个资源来完成(因为这是一个不同的资源,所以现在我有 /inventory/:id/properties/): How to handle updates in a REST API?

如果在保存属性的过程中出现问题怎么办?我无法轻松回滚已保存的库存项目,所以我最终得到了一个保存了一半的对象。

而且这在前端真的很难管理,因为如果在 属性 保存过程中发生一些错误,前端不应该再次保存库存。

似乎 InventoryProperties 实体如果没有它们的 Inventory 关系就永远不会使用。因此,您可以使用 JSONField Inventory.propetries 而不是单独的实体。

class Inventory(models.Model):
    props = models.JSONField(default=list)
    name = models.CharField(max_length=100, unique=True)


class InventorySerializer(serializers.ModelSerializer):
    class Meta:
        model = Inventory
        fields = ['name', 'props']

此序列化程序将在每次保存时重写所有 props in 1 SQL UPDATE 查询。作为奖励,您不需要支持 InventoryProperties.order 字段。

输入示例

{
   "name": "inv1",
   "props": [
      {"key": "size", "value": 30},
      {"key": "weight", "value": 16},
   ]
}

此外,您可以通过 key

添加访问属性的方法
class Inventory(models.Model):
    def get_prop(self, key: str):
        for prop in self.props:
            if prop["key"] == key:
                return prop["value"]
        return None
       

如果你想添加 JSON 的验证,你可以使用 this 方法

对于这种情况,您可以使用 django 事务,如果您的事务块中发生任何错误,它将回滚您的数据库事务。像这样的东西-

from django.db import transaction

with transaction.atomic():
    Inventory.objects.create(**kwargs)
    InventoryProperties.objects.create(**kwargs)

在事务块中,如果保存 InventoryProperties 出现任何错误,那么 Inventory Table 将被回滚。

我的解决方案是我创建了一个单独的端点,我可以在其中同时更新嵌套模型和多个模型,同时还提供典型的 RESTful 端点。 此端点使用原子事务,因此如果业务逻辑出现任何问题,则不会提交任何内容。