0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>На предыдущем уроке были рассмотрены связи "один к одному" и "один ко многим". Тогда же был упомянут и вид связи "многие ко многим".</p>
1
<p>На предыдущем уроке были рассмотрены связи "один к одному" и "один ко многим". Тогда же был упомянут и вид связи "многие ко многим".</p>
2
<p>Для этого вида связи тоже есть специальный тип поля:<a>ManyToManyField</a>. Этот вид связи подразумевает, что у объектов обеих моделей будет RelatedManager, отражающий множество связанных сущностей. Более того, это будет отдельный вид менеджера - ManyRelatedManager.</p>
2
<p>Для этого вида связи тоже есть специальный тип поля:<a>ManyToManyField</a>. Этот вид связи подразумевает, что у объектов обеих моделей будет RelatedManager, отражающий множество связанных сущностей. Более того, это будет отдельный вид менеджера - ManyRelatedManager.</p>
3
<p>Например, у нас есть следущие модели:</p>
3
<p>Например, у нас есть следущие модели:</p>
4
<p>У любого поста может быть несколько тегов, а может не быть ни одного. И одним тегом можно пометить более чем один пост. Поэтому пост и тег соотносятся как "многие ко многим". Заметьте, что опция on_delete не указана: кажется неверным удалять посты, если вдруг будет удалён тег, и уж точно не следует удалять теги при удалении помеченного ими поста.</p>
4
<p>У любого поста может быть несколько тегов, а может не быть ни одного. И одним тегом можно пометить более чем один пост. Поэтому пост и тег соотносятся как "многие ко многим". Заметьте, что опция on_delete не указана: кажется неверным удалять посты, если вдруг будет удалён тег, и уж точно не следует удалять теги при удалении помеченного ими поста.</p>
5
<p>Работают с такого рода связью следующим образом:</p>
5
<p>Работают с такого рода связью следующим образом:</p>
6
<p>Заметьте, что вставка производится в таблицу "blog_post_tags" - это вспомогательная таблица, которую создает Django ORM, чтобы связать таблицы "blog_post" и "blog_tag". В проекте для неё вы не найдёте соответствующей модели. Как видите, ORM может скрывать даже части схемы базы и берёт на себя всю работу.</p>
6
<p>Заметьте, что вставка производится в таблицу "blog_post_tags" - это вспомогательная таблица, которую создает Django ORM, чтобы связать таблицы "blog_post" и "blog_tag". В проекте для неё вы не найдёте соответствующей модели. Как видите, ORM может скрывать даже части схемы базы и берёт на себя всю работу.</p>
7
<p>Также обратите внимание на то, как происходит связывание тега и поста: ManyRelatedManager в атрибуте .tags экземпляра модели Post имеет специальный метод .add(). Он принимает произвольное количество тегов с которыми нужно связать данный пост. В свою очередь, со стороны модели Tag также есть ManyRelatedManager, позволяющий работать с постами, связанными с конкретным тегом.</p>
7
<p>Также обратите внимание на то, как происходит связывание тега и поста: ManyRelatedManager в атрибуте .tags экземпляра модели Post имеет специальный метод .add(). Он принимает произвольное количество тегов с которыми нужно связать данный пост. В свою очередь, со стороны модели Tag также есть ManyRelatedManager, позволяющий работать с постами, связанными с конкретным тегом.</p>
8
<p>Разорвать связь между объектами можно с помощью метода .remove() у любого из двух ManyRelatedManager, передав в аргументах метода перечень тегов для поста и наоборот. Но помните, что сами теги при этом удалены не будут. Объекты, связанные как "многие ко многим" удалять следует с помощью их собственных менеджеров, а не с помощью ManyRelatedManager.</p>
8
<p>Разорвать связь между объектами можно с помощью метода .remove() у любого из двух ManyRelatedManager, передав в аргументах метода перечень тегов для поста и наоборот. Но помните, что сами теги при этом удалены не будут. Объекты, связанные как "многие ко многим" удалять следует с помощью их собственных менеджеров, а не с помощью ManyRelatedManager.</p>
9
<h2>Связь через выделенную модель</h2>
9
<h2>Связь через выделенную модель</h2>
10
<p>По умолчанию на каждый ManyToManyField Django ORM создаст по вспомогательной таблице, в которой будет два столбца типа FOREIGN KEY, которые и будут ссылаться на сущности в связываемых таблицах. Такое неявное использование таблиц удобно в большинстве случаев.</p>
10
<p>По умолчанию на каждый ManyToManyField Django ORM создаст по вспомогательной таблице, в которой будет два столбца типа FOREIGN KEY, которые и будут ссылаться на сущности в связываемых таблицах. Такое неявное использование таблиц удобно в большинстве случаев.</p>
11
<p>Однако встречаются ситуации, когда факт связи между двумя сущностями хочется сопроводить какой-либо дополнительной информацией. Например, хочется знать, в какой момент времени некий тег был прикреплён к некоторому посту в блоге или какой пользователь этот тег посту присвоил. Здесь пригодилась бы отдельная модель, но не хочется терять все те удобства, которые даёт использование ManyRelatedManager.</p>
11
<p>Однако встречаются ситуации, когда факт связи между двумя сущностями хочется сопроводить какой-либо дополнительной информацией. Например, хочется знать, в какой момент времени некий тег был прикреплён к некоторому посту в блоге или какой пользователь этот тег посту присвоил. Здесь пригодилась бы отдельная модель, но не хочется терять все те удобства, которые даёт использование ManyRelatedManager.</p>
12
<p>Специально для подобных случаев ManyToManyField позволяет с помощью аргумента through указать конкретную модель, которая будет выступать связью. И разумеется, если модель будет указана, то ORM лишнюю таблицу создавать не будет.</p>
12
<p>Специально для подобных случаев ManyToManyField позволяет с помощью аргумента through указать конкретную модель, которая будет выступать связью. И разумеется, если модель будет указана, то ORM лишнюю таблицу создавать не будет.</p>
13
<p>Этот подвид связи достаточно интересен, но применяется наиболее редко. Более подробно почитать про особенности использования вспомогательной модели вы сможете в<a>специальном разделе документации</a>.</p>
13
<p>Этот подвид связи достаточно интересен, но применяется наиболее редко. Более подробно почитать про особенности использования вспомогательной модели вы сможете в<a>специальном разделе документации</a>.</p>