【问题标题】:Soft delete with unique constraint in DjangoDjango中具有唯一约束的软删除
【发布时间】:2020-01-27 07:07:49
【问题描述】:

我有这种布局的模型:

class SafeDeleteModel(models.Model):
    .....
    deleted = models.DateTimeField(editable=False, null=True)
    ......

class MyModel(SafeDeleteModel):
    safedelete_policy = SOFT_DELETE

    field1 = models.CharField(max_length=200)
    field2 = models.CharField(max_length=200)
    field3 = models.ForeignKey(MyModel3)
    field4 = models.ForeignKey(MyModel4)
    field5 = models.ForeignKey(MyModel5)

    class Meta:
        unique_together = [['field2', 'field3', 'field4', 'deleted'],]

这里的场景是我从不希望用户删除数据。相反,删除只会隐藏记录。但是,我仍然希望所有非软删除记录都尊重唯一键约束。基本上,我希望有尽可能多的重复删除记录,但只能存在一个唯一的未删除记录。所以我想包括“已删除”字段(由 django-safedelete 库提供),但问题是 Django 的唯一检查因“psycopg2.IntegrityError:重复键值违反唯一约束”而失败 ['field2', 'field3' , 'field4', 'deleted'] 因为 NULL 不“等于” NULL 并且它在 PostgreSQL 中产生 false。

有没有办法以我的 Django 模型布局强制执行 unique_together 约束?或者有没有更好的办法是物理删除记录,然后将其移动到存档数据库中,如果用户想要恢复记录,那么软件会在存档中查找记录并重新创建它?

【问题讨论】:

    标签: django database postgresql django-models soft-delete


    【解决方案1】:

    是的,从 Django 2.2 版开始,可以使用带有条件的 UniqueConstraint。

    查看此链接中的文档:https://docs.djangoproject.com/en/2.2/ref/models/constraints/#uniqueconstraint

    所以你的模型应该是这样的:

    class MyModel(SafeDeleteModel):
        safedelete_policy = SOFT_DELETE
    
        field1 = models.CharField(max_length=200)
        field2 = models.CharField(max_length=200)
        field3 = models.ForeignKey(MyModel3)
        field4 = models.ForeignKey(MyModel4)
        field5 = models.ForeignKey(MyModel5)
    
        class Meta:
            constraints = [
                models.UniqueConstraint(
                    fields=['field2', 'field3', 'field4'],
                    condition=Q(deleted=False),
                    name='unique_if_not_deleted')
            ]
    

    如果您使用的是不具备此功能的旧版本 Django,您可以创建具有部分唯一索引的迁移(请在此处查看此问题:Postgresql: Conditionally unique constraint)。

    至于您的第二个问题(将记录物理删除并将其移至其他位置会更好),这实际上取决于您的应用程序的特性。如果这些软删除不经常发生并且您的表仍然偏小,为了简单起见,我会将记录保留在同一个表中,但是如果表中的记录数开始快速增长并且它们会影响对该表的查询性能,那么您应该将记录移到其他地方。您必须评估复杂性和性能之间的权衡。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-30
      • 2012-10-26
      • 2019-06-15
      • 2012-09-02
      • 1970-01-01
      • 2016-10-08
      • 2018-08-05
      相关资源
      最近更新 更多