Как сделать Django OneToOneField взаимоисключающим для всех классов - PullRequest
0 голосов
/ 01 июля 2019

У меня есть: myARecord = models.OneToOneField (ClassA, ...), который используется двумя различными классами, B и C.

В администраторе Django он позволяет мне создать B-запись иC запись, которая ссылается на одну и ту же запись.Два экземпляра либо B, либо C не могут ссылаться на одну и ту же запись A.

1 Ответ

1 голос
/ 02 июля 2019

A OneToOneField - это в основном внешний ключ с установленным unique=True, что означает:

  1. , поскольку это внешний ключ, на экземпляр, на который он ссылается, могут ссылаться другие экземпляры, которые также имеют его в качестве значения внешнего ключа
  2. unique=True означает, что значение должно быть уникальным во всей таблице; это означает, что два экземпляра модели ClassB не могут иметь одинаковое значение внешнего ключа с указанием на ClassA, но один экземпляр ClassB может иметь то же значение внешнего ключа для модели ClassA, что и для одного экземпляра ClassC и т. д.

При этом навязывание строгих отношений один-к-одному таким способом может быть сделано только между двумя таблицами, а не тремя. В этом случае вы можете создать некоторую пользовательскую проверку, например:

class ClassB(models.Model):
    a_reference = models.OneToOneField(ClassA)

    def save(self, *args, **kwargs):
        class_c_instances_with_same_value = ClassC.objects.filter(a_reference=self.a_reference)
        if class_c_instances_with_same_value:
            raise ValidationError
        super(ClassB, self).save(*args, **kwargs)

но вы должны сделать это для всех ваших классов. Может быть, создать класс mixin и использовать его во всех классах, где вы хотите применить это.

Примечание: Как Кевин Кристофер Генри указал в комментариях, вы можете оставить свои проверки в методе clean() .

...