Множество отношений "многие ко многим" к одной и той же модели в Django
Учитывая следующую модель с двумя отношениями "многие ко многим":
class Child(models.Model):
name = models.CharField(max_length=80)
class Foo(models.Model):
bar = models.ManyToManyField(Child)
baz = models.ManyToManyField(Child)
Это дает ошибку:
accounts.foo: Accessor for m2m field 'bar' clashes with related m2m field 'Child.foo_set'. Add a related_name argument to the definition for 'bar'.
accounts.foo: Accessor for m2m field 'baz' clashes with related m2m field 'Child.foo_set'. Add a related_name argument to the definition for 'baz'.
Fine; Мне не нужна обратная связь. В соответствии с документами Django для related_name (что доступно только в ForeignKey, насколько я могу видеть), я могу установить related_name="+"
, а отсталые отношения выиграли 't быть создан:
class Child(models.Model):
name = models.CharField(max_length=80)
class Foo(models.Model):
bar = models.ManyToManyField(Child, related_name="+")
baz = models.ManyToManyField(Child, related_name="+")
Это не работает:
accounts.foo: Accessor for m2m field 'bar' clashes with related m2m field 'Child.+'. Add a related_name argument to the definition for 'bar'.
accounts.foo: Reverse query name for m2m field 'bar' clashes with related m2m field 'Child.+'. Add a related_name argument to the definition for 'bar'.
accounts.foo: Accessor for m2m field 'baz' clashes with related m2m field 'Child.+'. Add a related_name argument to the definition for 'baz'.
accounts.foo: Reverse query name for m2m field 'baz' clashes with related m2m field 'Child.+'. Add a related_name argument to the definition for 'baz'.
Что мне нужно сделать, чтобы избежать создания обратных отношений?
Ответы
Ответ 1
Я думаю, вам нужно просто дать двум полям разные связанные имена:
class Child(models.Model):
name = models.CharField(max_length=80)
class Foo(models.Model):
bar = models.ManyToManyField(Child, related_name="bar")
baz = models.ManyToManyField(Child, related_name="baz")
Если вы не указали связанное имя, оно пытается создать одно и то же имя доступа (foo_set
) дважды в модели Child
. Если вы дадите одно и то же родственное имя, он снова попытается создать один и тот же аксессуар дважды, поэтому вам нужно указать уникальные имена. С помощью приведенного выше кода для определения ваших моделей, затем с учетом Child
экземпляра c
вы можете получить доступ к связанным объектам Foo
с c.bar.all()
и c.baz.all()
.
Если вам не нужны обратные отношения, добавьте +
к каждому из (уникальных) связанных имен:
class Foo(models.Model):
bar = models.ManyToManyField(Child, related_name="bar+")
baz = models.ManyToManyField(Child, related_name="baz+")
Ответ 2
Вы недостаточно хорошо читали документацию Django. Здесь говорится:
Если у вас более одного ManyToManyField, указывающих на одну и ту же модель, и вы хотите подавить обратные отношения, установите каждое связанное имя в уникальное значение, заканчивающееся на +.
Атрибуты related_name
должны быть уникальными, а не одинаковыми.