Django 仅为新记录添加唯一约束

Django add unique constraint only for new records

我有一个 django 模型:

from django.db import models

class TestModel(models.Model):
  name = models.CharField("Name", null=False, blank=False, max_length=300)

一段时间后,我接到了添加唯一约束的任务,使我的新模型看起来像这样:

from django.db import models

class Test(models.Model):
  name = models.CharField("Title", null=False, blank=False, max_length=300, unique=True)

之后我需要做 makemigrationsmigrate。但是在我的数据库中,我已经有了重名的记录。

我的问题:我只想对新记录应用约束。有办法吗? (允许旧的重复项保留在数据库中,但阻止创建新的重复项)。

目前我的旧记录中 IntegrityError migrate

不,没有办法做到这一点,因为整个 table.

需要满足数据库级约束

您可以:

  • 首先迁移您的旧数据以使您的字段独一无二(例如在重复名称的末尾附加随机 strings/numbers)
  • 或者不在数据库级别添加约束,而是通过向您的字段添加自定义验证器,该验证器仅在验证时由 Django 检查。
  • 或者通过在节省时间时检查它(例如通过覆盖模型的 save() 方法)。

后两种方法的缺点是不能保证不会添加新的重复记录,例如通过批量添加或某人在将来添加代码而忘记验证。

请注意,这也意味着现有记录在尝试更改时不会生效。

最后一个替代方法是使用 blank=False, null=True, default=None, unique=True 创建一个新字段,您为现有行创建 None。如果 None,则显示现有的 name 字段(旧版),否则显示新名称字段。

一种方法是使用较新版本的 Django 原生支持的部分索引。这个想法是有一个布尔标志字段 duplicate 来标记允许重复的现有记录。该标志可以通过迁移填充:

class TestModel(models.Model):
    name = models.CharField("Name", null=False, blank=False, max_length=300)
    duplicate = models.BooleanField(default=False)

    constraints = [
      models.UniqueConstraint(fields=['name'],
                              condition=models.Q(duplicate=False)),
    ]