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)
之后我需要做 makemigrations
和 migrate
。但是在我的数据库中,我已经有了重名的记录。
我的问题:我只想对新记录应用约束。有办法吗? (允许旧的重复项保留在数据库中,但阻止创建新的重复项)。
目前我的旧记录中 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)),
]
我有一个 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)
之后我需要做 makemigrations
和 migrate
。但是在我的数据库中,我已经有了重名的记录。
我的问题:我只想对新记录应用约束。有办法吗? (允许旧的重复项保留在数据库中,但阻止创建新的重复项)。
目前我的旧记录中 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)),
]