【问题标题】:Deleting the m2m relationship instead of the the object itself in Django via REST API通过 REST API 在 Django 中删除 m2m 关系而不是对象本身
【发布时间】:2016-12-03 07:26:26
【问题描述】:

我有 3 个模型:UserUserItem(m2m thourgh)和 Item

User 可以创建Item。这会自动创建一个UserItem

不同的User 可以看到Item,并将其添加到自己的项目列表中,创建另一个UserItem

如果第一个 User 想要删除 Item,另一个 User 将不高兴 - 它需要保留,但对于最初的 User 来说似乎消失了。但是,如果只有一个User 仍然与之相关,那么Item 是可以安全删除的,并且应该删除以避免将死记录填满数据库。

我认为应该这样处理:

  1. Item deleteUser 调用 API
  2. Item pre_delete 检查item.user_set > 1
  3. 如果True,手动删除UserItem,将Item留在原处。如果False,删除Item

这种方式UserItem 不会通过 API 公开,并且简化了对客户端的管理。

这是正确/常见的方法吗?如何用 Django 完成?我不确定如何在不引发异常的情况下防止 Item.delete()pre_delete 内发生,但由于这是预期的行为,引发异常似乎不是正确的方法。

【问题讨论】:

    标签: django django-models many-to-many django-rest-framework django-signals


    【解决方案1】:

    这对我来说似乎很好。但是,您可以覆盖 Item 模型上的 delete() 方法,而不是使用信号。有关 save() 方法的示例,请参阅 the official documentation。您的delete() 方法也可以同样实现,即当还有其他具有UserItem 的用户时,它不会调用super()

    【讨论】:

      【解决方案2】:

      来自django docs:“如果你想要自定义删除行为,你可以重写delete()方法。”

      我想这就是你想要的:

      def delete(self, *args, **kwargs):
          if item.user_set > 1:
              return
          else:
              super(Item, self).delete(*args, **kwargs) # Call the "real" delete() method.
      

      【讨论】:

      • 我仍然需要删除UserItem(而不是返回)。我不知道该怎么做 - 我知道项目 ID,但我需要获取用户 ID,否则我无法删除正确的用户项目
      【解决方案3】:

      这就是我的选择。它将逻辑保留在model 中,但view 为其提供了当前的user

      我认为最好远离delete(),因为管理员用户应该能够删除项目而不管相关用户如何,并且没有简单的方法可以访问delete() 中的当前user

      欢迎提出建设性的批评!

      models.py

      class Item(TimeStampedModel):
      
          ...
      
          def delete_item_or_user_item(self, user):
          """
          Delete the Item if the current User is the only User related to it.
          If multiple Users are related to the Item, delete the UserItem.
          """
          if UserItem.objects.filter(item=self).count() > 1:
              UserItem.objects.filter(item=self, user=user).delete()
          else:
              self.delete()
      

      views.py

      class ItemViewSet(viewsets.ModelViewSet):
      
          ...
      
          def perform_destroy(self, instance):
              instance.delete_item_or_user_item(self.request.user)
      

      【讨论】:

        猜你喜欢
        • 2019-01-05
        • 1970-01-01
        • 2016-05-07
        • 2020-05-03
        • 2021-03-03
        • 2020-11-08
        • 1970-01-01
        • 2017-02-19
        • 1970-01-01
        相关资源
        最近更新 更多