Skip to main content
 首页 » 编程设计

python之如果 Django ORM 要使用错误的 PK 值,是否需要自定义 ForeignKey 子类

2025年05月04日31lyhabc

我正在处理的项目在数据库中有脏数据。基本上,最初的设计者创建了外键字段,但没有强制执行它们的参照完整性。现在有无效的 FK 值,实际上并不指向存在的记录。通常我会简单地删除这些无效的 FK 值,但位于此数据库上的应用程序另外使用存储在这些 FK 字段中的文字数字 0 来指示其他信息。实际上没有主键=0的记录。

我已经将这个有缺陷的表设计包装在 Django 的 ORM 类和 ForeignKey 字段中,但不出所料,当它在 ForeignKey 字段的另一端找不到记录时,会抛出很多 DoesNotExist 异常。我一直在尝试找出一种方法,仅针对这个项目,安静地捕获此异常,而不必在可能抛出此异常的任何地方用 try/except block 乱扔我的代码。在这种情况下,我只是想防止错误被 Django ORM 抛出。

我正在尝试通过覆盖 get() 方法并使用 use_for_related_field=True 类属性来使用自定义管理器来执行此操作。尽管在 ForeignKey 具有无效键值的情况下,显然并未使用自定义管理器的 get() 方法。

class FWManager(models.Manager): 
    """ 
    FW's data is "dirty".  Primarily it isn't enforcing referential integrity on  
    many of it's foreign key fields leading to oprphaned records.  Django throws a 
    DoesNotExist exception in this case which is troublesome  having to catch it for 
    any fk field access. 
 
    Custom FWManager will silently "eat" the DoesNotExist error and return None 
    instead. 
    """ 
 
    use_for_related_fields=True 
 
    def get(self, *args, **kwargs): 
 
        #init 
        retval = None 
 
        try: 
            retval = super(FWManager, self).get(*args, **kwargs) 
        except: 
            # silently eat errors 
            pass 
 
        return retval 

我需要一种方法来捕获并吃掉潜在自定义 ForeignKey 上的 DoesNotExist 错误,我正在寻找一个如何处理此问题的示例。或者也许有人可以推荐更好的方法。

请您参考如下方法:

我认为应该有更好的可能性来解决这个问题,因为您的解决方案仍然没有为您的数据库带来任何完整性。可能性是:

  • 更改您的模型:将 FK 的参数设置为 null=True 并将零更改为 None
  • 将所有带有“0”的 FK 设置为另一个值并创建一个相关的“虚拟对象”,代表“已删除”的对象

默默地失败(所有)异常也会给你带来很多麻烦,因为你可能会在不知道的情况下遇到其他问题......