外部キー間で一意性制約を検証する方法(django) 質問する

外部キー間で一意性制約を検証する方法(django) 質問する

次のような(簡略化された)データ構造があります。

Site
-> Zone
   -> Room
      -> name

各部屋の名前をサイトごとに一意にしたいです。

各ゾーンに一意性を持たせたいだけなら、次のようにすればよいことがわかっています。

class Room(models.Model):
    zone = models.ForeignKey(Zone)
    name = models.CharField(max_length=255) 

    class Meta:
        unique_together = ('name', 'zone')

しかし、私が本当に望んでいることはできません。

class Room(models.Model):
    zone = models.ForeignKey(Zone)
    name = models.CharField(max_length=255) 

    class Meta:
        unique_together = ('name', 'zone__site')

提案されたようにvalidate_uniqueメソッドを追加してみましたこの質問:

class Room(models.Model):
    zone = models.ForeignKey(Zone)
    name = models.CharField(max_length=255) 

    def validate_unique(self, exclude=None):
        qs = Room.objects.filter(name=self.name)
        if qs.filter(zone__site=self.zone__site).exists():
            raise ValidationError('Name must be unique per site')

        models.Model.validate_unique(self, exclude=exclude)

しかし、Room オブジェクトを保存するときにvalidate_unique が呼び出されないので、validate_unique のポイント/実装を誤解しているに違いありません。

このチェックを実装する正しい方法は何でしょうか?

ベストアンサー1

モデルを保存するときに、メソッドは単独では呼び出されません。これを実現する 1 つの方法は、validate_uniqueモデルが保存されるときにメソッドを呼び出すカスタム save メソッドを用意することです。

class Room(models.Model):
    zone = models.ForeignKey(Zone)
    name = models.CharField(max_length=255) 

    def validate_unique(self, exclude=None):
        qs = Room.objects.filter(name=self.name)
        if qs.filter(zone__site=self.zone__site).exists():
            raise ValidationError('Name must be unique per site')

    def save(self, *args, **kwargs):
        self.validate_unique()
    
        super(Room, self).save(*args, **kwargs)

おすすめ記事