首页 > 解决方案 > Django post_delete:计算所有具有一个与已删除对象匹配的属性的对象

问题描述

我有一个自定义函数,在删除模型订单的对象时调用,我为此使用 post_delete。

模型“订单”的实例始终具有 ForeignKey“用户”。删除模型“订单”的对象时,我想检查是否存在具有相同“用户”的模型“订单”的其他实例。

def delete_reverse(sender, **kwargs):
try:
    if Orders.objects.filter(user__equal=kwargs['instance'].user).count() == 1:
        kwargs['instance'].user.delete()
    else:
        ...         
except:
    pass
post_delete.connect(delete_reverse, sender=Orders)

不幸的是,if 条件不起作用,即即使相应条目的计数应该为 1,它也不为真。您看到我的 count() 函数有什么问题吗?

标签: pythondjangofiltercountsignals

解决方案


我认为这段代码存在一些问题:

  1. 您似乎使用了__equal字段查找,但是标准字段查找列表中存在此查找 [Django-doc],最接近的是__exact,但这里可能没有必要;

  2. 您使用“一揽子例外”(!),这是一种严重的反模式:如果某些事情失败了,那么您将永远不会被告知。就像Python 之禅所说:永远不要静默传递异常,除非显式静默

  3. 删除后意味着删除已经发生,因此此时实例不再在数据库中,如文档中所述:

    请注意,该对象将不再存在于数据库中,因此请务必小心处理此实例。

因此,最后一项意味着您可能想要检查计数是否为零(因此 no Orderwith thatuser_id不再存在):

@receiver(post_save, sender=Orders)
def delete_reverse(sender, instance, **kwargs):
    if not Order.objects.filter(user_id=instance.user_id).exists():
        instance.user.delete()

但是请注意,即使这样做,仍然存在数据库可以包含Users 而没有任何Orders 的场景:例如,当我们更改user_idan 的Order时,以前的用户可能不再拥有,但此功能将无法获取触发。因此,定期检查数据库以查找此类情况可能是值得的。

此外,我不知道删除是否User是个好主意。如果这是 Django 中的身份验证模型,则可能会导致管理员用户被删除,例如意外地在他们的名字上下了一个订单,然后该订单被删除。此外,删除用户可能会导致大量删除(涉及该用户的所有类型的“实体”)。

注意:Django 模型通常有一个单数名称,所以我建议,就像我在答案中所做的那样,将Orders模型重命名为Order.


推荐阅读