Перейти к содержанию

Отсрочка комментариев

Самоссылочные модели

Если вы хотите сослаться на одну и ту же модель для создания связи во время объявления, необходимо объявить модель, на которую ссылается ссылка, как ForwardRef, так как класс не готов во время объявления, и Python по умолчанию не позволяет ссылаться на него.

Хотя может возникнуть желание использовать будущие комментарии или просто ссылаться на имя «», он не сработает, так как ormar предназначен для использования с явно объявленными ForwardRef.

Во-первых, необходимо импортировать необходимые ссылки из импорта.

1
Из типизированного импорта Forwardref

Теперь нам нужна образец модели и ссылка на ту же модель, которая будет использоваться для создания самоссылочных отношений.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Create the Forwardref to model Person
PersonRef = Forwardref("Person")


Класс Персон (модель):
    ormar_config = base_ormar_config ()

    id: int = ormar.Integer(primary_key =True)
    name: str = ormar.String(max_length =100)
    #Использование Forwardref as to parameter
    Supervisor: PersonRef = ormar.ForeignKey(PersonRef, related_name ="employees")

Это все просто. Но перед началом работы с моделью необходимо обновить ссылки вручную, чтобы они создали реальную модель.

!!!предупреждает, что при попытке использовать модель без обновления ссылки будет генерироваться исключение ModelError. Таким образом, в приведенном выше примере любой вызов, такой как следующий, приведет к исключению python # creation of model - exception await Person.objects.create(name="Test") # initialization of model - exception Person2(name="Test") # usage of model's QuerySet - exception await Person2.objects.get()

Чтобы обновить ссылку, вызывайте метод update_forward_refs для каждой модели, имеющей предыдущую ссылку, только после объявления всех связанных моделей.

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
PersonRef = Forwardref("Person")


Класс Персон (модель):
    ormar_config = base_ormar_config ()

    id: int = ormar.Integer(primary_key =True)
    name: str = ormar.String(max_length =100)
    Supervisor: PersonRef = ormar.ForeignKey(PersonRef, related_name ="employees")


((): update_forward (

Конечно, для аргументов to и through можно сделать одно и то же действие с отношениями ManyToMany совершенно одинаковым образом.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# declare the reference
ChildRef = Forwardref("Child")

Class ChildFriend(Ormar.Model):
    ormar_config = base_ormar_config ()

Class Child(Ormar.Model):
    ormar_config = base_ormar_config ()

    id: int = ormar.Integer(primary_key =True)
    name: str = ormar.String(max_length =100)
    # use it in relation
    Friends = ormar.ManyToMany(ChildRef, through=ChildFriend)
                               related_name ="alo_friends")


Дистрибьют-update_refs

Взаимосвязи между моделями

Для связывания нескольких различных моделей друг с другом можно использовать те же механизмы и логику, что и самоссылочные модели.

Конечно, ormar создает обратную связь между двумя сторонами связи с использованием указанного (или по умолчанию) related_name.

Однако, если требуется наличие двух (или более) связей между любыми двумя моделями, которые по какой-либо причине должны храниться с обеих сторон (следовательно, объявлять одно отношение на одной модели и другое на второй модели), то для этого потребуется использовать Forwardref.

Рассмотрим простой пример ниже.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Teacher is not yet defined
TeacherRef = Forwardref("Teacher")


Класссный студент (Ormar):
    ormar_config = base_ormar_config ()

    id: int = ormar.Integer(primary_key =True)
    name: str = ormar.String(max_length =100)
    Мы используем ссылки на фактическую модель
    primary_teacher: Teacherref = ormar.ForeignKey(Teacherref,
                                                   related_name ="own_students")


Class StudentTeacher(модель):
    ormar_config = base_ormar_config.copy (tablename ='students_x_teachers')


Класс Teacher(модель ormar.):
    ormar_config = base_ormar_config ()

    id: int = ormar.Integer(primary_key =True)
    name: str = ormar.String(max_length =100)
    #Мы нуждаемся в исследованиях для других связей, как это происходит
    Students = ormar.ManyToMany(Student, through=StudentTeacher),
                                related_name ="teachers")

# now the Teacher model is already defined we can update references
Student update_forward_refs ()

!!! Внимание Помните, что, независимо от количества заданных связей, related_name должна быть уникальной в связанной модели.