Как привязать несколько моделей к одному ManyToManyField? - PullRequest
0 голосов
/ 16 января 2019

Есть, например, такие классы:

class A(models.Model):
 id = models.CharField(max_length=256, primary_key=True)
 mtm = models.ManyToManyField(B, C, D)

class B(models.Model):
 id = models.CharField(max_length=256, primary_key=True)
class C(models.Model):
 id = models.CharField(max_length=256, primary_key=True)
class D(models.Model):
 id = models.CharField(max_length=256, primary_key=True)

Я знаю класс реализации поля И неправильно, сделал так, чтобы было понятнее. Вы должны иметь эту модель И иметь отношения ManyToMany с моделями B, C, D. Как это может быть сделано? Есть ли специальное поле?

1 Ответ

0 голосов
/ 16 января 2019

На момент написания статьи это невозможно. A ManyToManyField [Django-doc] имеет позиционный to аргумент с:

<b>class ManyToManyField(to, **options)</b>

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

Это также может создать некоторую путаницу: что должен mtm вернуть для some_a.mtm.all()? Все связанные B объекты? Кортежи объектов B, C и D? Каким должно быть название перевернутых отношений?

Это, однако, не означает, что вы не можете эмулировать такое отношение. Вы можете сделать модель, которая действует как отношение. Фактически, если вы определите ManyToManyField, Django создаст таблицу, в которой будут храниться данные из этого отношения.

Таким образом, мы можем определить такую ​​модель как:

class ABCDRel(models.Model):
    a = models.ForeignKey(A, on_delete=models.CASCADE, related_name='mtm')
    b = models.ForeignKey(B, on_delete=models.CASCADE, related_name='mtm')
    c = models.ForeignKey(C, on_delete=models.CASCADE, related_name='mtm')
    d = models.ForeignKey(D, on_delete=models.CASCADE, related_name='mtm')

Затем мы можем, например, получить QuerySet всех связанных ABCDRelation с:

some_a.<b>mtm.all()</b>

Или вы можете получить QuerySet всех связанных B объектов через эту связь с:

B.objects.filter(<b>mtm__a=some_a</b>)

Отношение может содержать дополнительные данные, но, по сути, таким образом хранит «кортежи» того, как объекты моделей связаны друг с другом.

Таким образом, создается модель сущности-отношения, более или менее похожая на:

Entity-relation model of this modeling

...