Как сделать поля уникальными для других моделей, ссылающихся на тот же ForeignKey - PullRequest
0 голосов
/ 14 марта 2019

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

В моем случае я пытаюсь сделать так, чтобы 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 Ответ

0 голосов
/ 14 марта 2019

Вы можете использовать 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('...')

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

...