为什么 Django 唯一约束不起作用?

时间:2021-07-18 17:55:37

标签: python django

我已将 UniqueConstraint 添加到 Meta 类的约束数组中,该类是 User 表的子类。

class User(AbstractBaseUser):
...
    class Meta:
         verbose_name = _("account")
        verbose_name_plural = _("accounts")
        indexes = [
            models.Index(name="email_index", fields=["email"])
        ]
        constraints = [
            models.CheckConstraint(name="check_birth_date", check=Q(birth_date__lt=f"{datetime.date.today()}")),
            models.CheckConstraint(name="check_phone_number", check=Q(phone_number__regex=r"^09(1[0-9]|2[0-9]|3[0-9])[0-9]{3}[0-9]{4}$")),
            models.UniqueConstraint(name="username_email_unique", fields=["username", "email"])
        ]

我的期望是防止用户输入具有相同值的用户名和电子邮件,但实际上没有用,用户可以在没有得到 IntegrityError 的情况下这样做 此外,我正在使用 Postgresql

1 个答案:

答案 0 :(得分:4)

<块引用>

我的期望是防止用户输入具有相同值的用户名和电子邮件。

:如果指定两个或多个字段,则意味着这些字段的组合应该是唯一的。换句话说,如果有用户A和用户B,它只会拒绝创建B,如果两者 .username.email 相同。

您需要使这两个字段分别唯一。您可以使用 unique=… parameter [Django-doc]:

class User(AbstractBaseUser):
    username = models.CharField(max_length=255, unique=True)
    email = models.EmailField(unique=True)
    # …

或者,如果您想通过约束来做到这一点,您可以创建两个 UniqueConstraint,每个用于一个字段:

class User(AbstractBaseUser):
    # …
    class Meta:
        # …
        constraints = [
            models.CheckConstraint(name="check_birth_date", check=Q(birth_date__lt=f"{datetime.date.today()}")),
            models.CheckConstraint(name="check_phone_number", check=Q(phone_number__regex=r"^09(1[0-9]|2[0-9]|3[0-9])[0-9]{3}[0-9]{4}$")),
            models.UniqueConstraint(name="username_unique", fields=["username"]),
            models.UniqueConstraint(name="email_unique", fields=["email"])
        ]

如果您想防止为每条记录的 usernameemail 字段输入 相同 值,则需要添加额外的 {{3 }}:

from django.db.models import F, Q

class User(AbstractBaseUser):
    # …
    class Meta:
        # …
        constraints = [
            # …
            models.CheckConstraint(check=~Q(username=F('email')), name='username_email_unique')
        ]