想象一下这样的情景:

class User(models.Model):
     name = CharField(max_length=80)

class TelephoneNumber(models.Model):
     phone_number = CharField(max_length=10)
     user = ForeignKey(User)
     is_default_number = BooleanField

假设我想保证每个用户只有一个默认电话号码。我们可以拥有任意数量的is_default_number == False,但是对于每个user,应该只有一个is_default_number == True
有没有任何方法可以通过django在数据库级别强制执行此操作?我知道纯python的一个简单解决方案是:
class TelephoneNumber(models.Model):
    phone_number = CharField(max_length=10)
    user = ForeignKey(User)
    is_default_number = BooleanField

    def save(self, *args, **kwargs):
         other_defaults_same_user = TelephoneNumber.objects.filter(
              user=self.user,
              is_default_number=True
         ).exclude(
              pk=self.pk
         )

         if self.is_default_number and other_defaults_same_user.exists():
              raise ValidationError("Can't have two phone numbers as default"
                                    " for one user.")

         super(TelephoneNumber, self).save(*args, **kwargs)

但这很容易受到竞争条件错误的影响,我不喜欢每次保存时都要进行额外的读取(不过,这种额外的读取可能在某些时候是必要的)。在Django有什么方法可以做到这一点吗?如果我们必须使答案数据库依赖,我会有兴趣看到答案,但显然一个后端独立的最好。

最佳答案

为什么不在用户模型中将默认电话号码设为外键?

07-28 09:57