Подтвердить что ты не робот

Множество отношений "многие ко многим" к одной и той же модели в 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'.

Что мне нужно сделать, чтобы избежать создания обратных отношений?

4b9b3361

Ответ 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 должны быть уникальными, а не одинаковыми.