Как сделать поля уникальными с помощью других моделей, ссылающихся на тот же внешний ключ

#python #django #django-models

#python #django #django-модели

Вопрос:

Есть ли способ сделать поля модели уникальными для других моделей, ссылающихся на тот же внешний ключ?

В моем случае я пытаюсь сделать так, чтобы names из Attribute моделей с одинаковым Obj значением были уникальными. Пример: если существует CharAttribute с name='Types' и obj=1 , не может быть другого CharAttribute с name='Types' и obj=1 , ни IntAttribute с name='Types' и obj=1

 class Obj (models.Model):
    name = models.CharField(max_length=40)


class CharAttribute (models.Model):
    name = models.CharField(max_length=40)
    obj = models.ForeignKey(Obj, on_delete=models.CASCADE)


class IntAttribute (models.Model):
    name = models.CharField(max_length=40)
    obj = models.ForeignKey(Obj, on_delete=models.CASCADE)
  

Моя текущая идея решения была бы примерно такой:

 def clean_fields(self, exclude=None):
    super().clean_fields(exclude=exclude)
    for other_name in IntAttribute.objects.filter(obj=self.obj):
        if self.name == other_name:
            raise ValidationError(
                ('Attributes of the same object may not have the same name, %(name) s already exists for '
                 '%(object) s' % {'name': self.name, 'object': self.obj.name})
            )

    for other_name in CharAttribute.objects.filter(obj=self.obj):
        if self.name == other_name:
            raise ValidationError(
                ('Attributes of the same object may not have the same name, %(name) s already exists for '
                 '%(object) s' % {'name': self.name, "object": self.obj.name})
            )
  

Но создание другого цикла for для каждого возможного будущего, созданного Attribute , кажется повторяющимся, и должен быть лучший способ выполнения этой задачи.

Заранее благодарю вас за отзыв.

Ответ №1:

Вы можете использовать unique_together, чтобы убедиться, что ни одна комбинация полей не повторяется в модели:

 class CharAttribute (models.Model):
    name = models.CharField(max_length=40)
    obj = models.ForeignKey(Obj, on_delete=models.CASCADE)

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

Между моделями вам придется выполнять проверку вручную:

 class CharAttribute (models.Model):
    name = models.CharField(max_length=40)
    obj = models.ForeignKey(Obj, on_delete=models.CASCADE)

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

    def clean(self):
        if IntAttribute.objects.filter(name=self.name, obj=self.obj).exists():
            raise ValidationError('...')

  

Тот же метод применяется для другой модели.

Комментарии:

1. Я чувствую себя идиотом с циклами for, спасибо, ха-ха