次のような(簡略化された)データ構造があります。
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)