次のようなものを想像してみてください。
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
ユーザーごとにデフォルトの電話番号が1つだけであることを保証したいとします。必要な数だけ持つことができますis_default_number == False
が、それぞれに対して、を持つものは1つuser
だけにする必要があります。is_default_number == True
Djangoを介してデータベースレベルでこれを実施する方法はありますか?純粋なPythonの簡単な解決策の1つは、次のとおりです。
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でこれを達成する方法はありますか?回答をデータベースに依存させる必要がある場合は、回答を確認したいと思いますが、明らかにバックエンドに依存しないものが最適です。