【问题标题】:Can I get the current user in a model delete method (to delete the appropriate m2m through) in Django?我可以在 Django 中通过模型删除方法(删除适当的 m2m)获取当前用户吗?
【发布时间】:2016-08-05 16:07:14
【问题描述】:

这是我想要做的:

class Item(TimestampedModel):
    ....
    def delete(self, *args, **kwargs):

        # Other users have linked to this item, delete the link
        if UserItem.objects.filter(item=self).count() > 1:
            # TODO Delete the UserItem linking the current User to this Item

        # No one else has linked to this item, delete the item
        else:
            super(Item, self).delete(*args, **kwargs)

class UserItem(TimeStampedModel):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    item= models.ForeignKey(Item, on_delete=models.CASCADE)

【问题讨论】:

  • 这种事情(用户是已知的)通常在视图级别完成。
  • 我想了很多,但希望在模型中保留这个删除逻辑
  • 你可以破解 save 方法,在 kwargs 中传入用户并在调用 super 之前弹出它,但你仍然需要从视图级别传入用户。

标签: django django-models m2m


【解决方案1】:

如果您只想确保在删除之前Item 未被超过 1 个用户使用,那么您可以执行以下操作:

添加related_name方便使用:

class UserItem(TimeStampedModel):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    item= models.ForeignKey(Item, on_delete=models.CASCADE, ralated_name='used_by')

在删除之前你可以这样检查:

if self.used_by.values('user').distinct().count() > 1:
   # THIS MEANS THERE ARE MORE THAN ONE USER LINKING TO THIS ITEM
else:
   super(Item, self).delete(*args, **kwargs)

虽然如果您选择实现这一点,那么我假设只有“链接”到该项目的用户才能删除它,因此没有人可以删除另一个项目。

通常,最好在视图中执行这种逻辑(正如@wobbily_col 评论的那样)。

【讨论】:

    【解决方案2】:

    delete的后置条件应该是模型实例不再存在于数据库中。

    条件删除是一种位于视图和模型之间的业务逻辑。通过这种观察,您可以自己定义函数的名称和参数。说detach_item_from_user(item, user)

    另请参阅“胖模型、实用模块、精简视图、愚蠢模板”下的“Django 的两个勺子”。

    【讨论】:

      【解决方案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)
      

      【讨论】:

      • 这与我的回答有何不同(除了您决定更改三个名称中的两个)?
      • 代码,它给出了解决方案的上下文,显示了如何和在哪里,并让下一个需要答案的人更容易获得解决方案,因为当我查看别人的问题时带有代码的答案是我认为最有帮助的答案。
      猜你喜欢
      • 1970-01-01
      • 2020-08-17
      • 2020-01-31
      • 2010-11-18
      • 1970-01-01
      • 1970-01-01
      • 2018-02-07
      • 2013-06-09
      • 2016-05-05
      相关资源
      最近更新 更多