Django条件唯一组合

8 投票
3 回答
6829 浏览
提问于 2025-04-17 06:55

我有一个模型,长得像这样:

class LibraryEntry(models.Model):
  host_lib_song_id = models.IntegerField()
  song = models.CharField(max_length=200)
  artist = models.CharField(max_length=200)
  album = models.CharField(max_length=200)
  owning_user = models.ForeignKey(User)
  is_deleted = models.BooleanField(default=False)

现在,如果我进行一个选择,条件是 is_deleted=False,那么 host_lib_song_idowning_user 的组合应该是唯一的。我该怎么表达这个意思呢?

3 个回答

2

如果你使用的是Django 2.2或更高版本,可以使用UniqueConstraint。你可以在这里查看完整的答案。

4

你不能通过 Meta.unique_together 这个限制来实现这个功能,而是要通过 Django 的模型验证 来做到:

class LibraryEntry(models.Model):
    def clean(self):
        from django.core.exceptions import ValidationError
        try:
            # try to find a duplicate entry and exclude 'self'
            duplicate = LibraryEntry.objects.exclude(pk=self.pk)\
                .get(owning_user=self.owning_user, 
                     host_lib_song_id=self.host_lib_song_id,
                     is_deleted=False)
            raise ValidationError('Library Entry already exists!')
        except: LibraryEntry.DoesNotExist:
            # no duplicate found
            pass
12

重写 validate_unique 方法来检查唯一性,当 is_deletedFalse 时,这样做更合适:

...

def validate_unique(self, exclude=None):
    if not self.is_deleted and \
       LibraryEntry.objects.exclude(pk=self.pk).filter(host_lib_song_id=self.host_lib_song_id, owning_user=self.owning_user).exists():
        raise ValidationError('Some error message about uniqueness required')
    super(LibraryEntry, self).validate_unique(exclude=exclude)

撰写回答