1

次のようなものを想像してみてください。

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でこれを達成する方法はありますか?回答をデータベースに依存させる必要がある場合は、回答を確認したいと思いますが、明らかにバックエンドに依存しないものが最適です。

4

2 に答える 2

4

default_phone_numberをユーザーモデルの外部キーにしないのはなぜですか?

于 2012-08-29T01:55:03.823 に答える
0

モデルフィールド検証を使用します-https ://docs.djangoproject.com/en/dev/ref/models/instances/#validating-objects

if self.is_default_number and TelephoneNumber.objects.filter(user=self.user, is_default_number=True).exclude(id=self.id).exists():
#throw ValidationError

しかし、余分な読み取りを避けることはできないと思います。

于 2012-08-29T04:30:19.180 に答える